github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/atomickit/once.go (about) 1 /* 2 * Copyright 2020 Insolar Network Ltd. 3 * All rights reserved. 4 * This material is licensed under the Insolar License version 1.0, 5 * available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 6 */ 7 8 package atomickit 9 10 import ( 11 "sync" 12 "sync/atomic" 13 ) 14 15 type Once struct { 16 done uint32 17 m sync.Mutex 18 } 19 20 func (p *Once) IsDone() bool { 21 return atomic.LoadUint32(&p.done) != 0 22 } 23 24 func (p *Once) GetDone() uint32 { 25 return atomic.LoadUint32(&p.done) 26 } 27 28 func (p *Once) Do(f func()) { 29 if atomic.LoadUint32(&p.done) == 0 { 30 p.doSlow(func() uint32 { 31 f() 32 return 1 33 }) 34 } 35 } 36 37 func (p *Once) DoWithValue(f func() uint32) { 38 if atomic.LoadUint32(&p.done) == 0 { 39 p.doSlow(f) 40 } 41 } 42 43 func (p *Once) doSlow(f func() uint32) { 44 p.m.Lock() 45 defer p.m.Unlock() 46 if atomic.LoadUint32(&p.done) == 0 { 47 defer atomic.CompareAndSwapUint32(&p.done, 0, 1) // set 1 when f() has returned 0 48 atomic.StoreUint32(&p.done, f()) 49 } 50 }