github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/utils/spin_lock.go (about)

     1  package utils
     2  
     3  import (
     4  	"runtime"
     5  	"sync/atomic"
     6  )
     7  
     8  // SpinLock implements a simple atomic spin lock, the zero value for a SpinLock is an unlocked spinlock.
     9  type SpinLock struct {
    10  	f uint32
    11  }
    12  
    13  // Lock locks sl. If the lock is already in use, the caller blocks until Unlock is called
    14  func (sl *SpinLock) Lock() {
    15  	for !sl.TryLock() {
    16  		runtime.Gosched() // allow other goroutines to do work.
    17  	}
    18  }
    19  
    20  // Unlock unlocks sl, unlike [Mutex.Unlock](http://golang.org/pkg/sync/#Mutex.Unlock),
    21  // there's no harm calling it on an unlocked SpinLock
    22  func (sl *SpinLock) Unlock() {
    23  	atomic.StoreUint32(&sl.f, 0)
    24  }
    25  
    26  // TryLock will try to lock sl and return whether it succeed or not without blocking.
    27  func (sl *SpinLock) TryLock() bool {
    28  	return atomic.CompareAndSwapUint32(&sl.f, 0, 1)
    29  }
    30  
    31  // String is human readable lock state
    32  func (sl *SpinLock) String() string {
    33  	if atomic.LoadUint32(&sl.f) == 1 {
    34  		return "Locked"
    35  	}
    36  	return "Unlocked"
    37  }