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