github.com/andy2046/gopie@v0.7.0/pkg/spinlock/spinlock.go (about)

     1  // Package spinlock implements Spinlock.
     2  package spinlock
     3  
     4  import (
     5  	"runtime"
     6  	"sync/atomic"
     7  )
     8  
     9  // Locker is the Spinlock implementation.
    10  type Locker struct {
    11  	noCopy noCopy
    12  	lock   uintptr
    13  }
    14  
    15  // New creates a Locker.
    16  func New() *Locker {
    17  	return &Locker{}
    18  }
    19  
    20  // Lock wait in a loop to acquire the spinlock.
    21  func (l *Locker) Lock() {
    22  	for !atomic.CompareAndSwapUintptr(&l.lock, 0, 1) {
    23  		runtime.Gosched()
    24  	}
    25  }
    26  
    27  // Unlock release the spinlock.
    28  func (l *Locker) Unlock() {
    29  	atomic.StoreUintptr(&l.lock, 0)
    30  }
    31  
    32  // TryLock try to acquire the spinlock,
    33  // it returns true if succeed, false otherwise.
    34  func (l *Locker) TryLock() bool {
    35  	return atomic.CompareAndSwapUintptr(&l.lock, 0, 1)
    36  }
    37  
    38  // IsLocked returns true if locked, false otherwise.
    39  func (l *Locker) IsLocked() bool {
    40  	return atomic.LoadUintptr(&l.lock) == 1
    41  }
    42  
    43  // noCopy may be embedded into structs which must not be copied
    44  // after the first use.
    45  type noCopy struct{}
    46  
    47  // Lock is a no-op used by -copylocks checker from `go vet`.
    48  func (*noCopy) Lock()   {}
    49  func (*noCopy) Unlock() {}