github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/atomickit/flag_once.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package atomickit 7 8 import ( 9 "runtime" 10 "sync/atomic" 11 ) 12 13 type OnceFlag struct { 14 done int32 15 } 16 17 func (p *OnceFlag) IsSet() bool { 18 return atomic.LoadInt32(&p.done) == 1 19 } 20 21 func (p *OnceFlag) Set() bool { 22 return atomic.CompareAndSwapInt32(&p.done, 0, 1) 23 } 24 25 func (p *OnceFlag) DoSet(f func()) bool { 26 if !atomic.CompareAndSwapInt32(&p.done, 0, -1) { 27 return false 28 } 29 p.doSlow(f) 30 return true 31 } 32 33 func (p *OnceFlag) DoSpin(f func()) bool { 34 if !atomic.CompareAndSwapInt32(&p.done, 0, -1) { 35 for !p.IsSet() { 36 runtime.Gosched() 37 } 38 return false 39 } 40 p.doSlow(f) 41 return true 42 } 43 44 func (p *OnceFlag) doSlow(f func()) { 45 defer atomic.StoreInt32(&p.done, 1) 46 f() 47 } 48