-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathspinlock.go
51 lines (42 loc) · 1.14 KB
/
spinlock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package spinlock
import (
"runtime"
"sync"
"sync/atomic"
)
const (
unlocked uint32 = iota
locked
)
// SpinLock implements a atomic spin lock, the zero value for a SpinLock is an unlocked spin-lock.
// After the first use, we SHOULD NOT copy the value.
type SpinLock struct {
s uint32
}
// TryLock will try to acquire the lock and return it succeed or not.
func (l *SpinLock) TryLock() bool {
return atomic.CompareAndSwapUint32(&l.s, unlocked, locked)
}
// Lock will try to acquire the spin-lock, if the lock is already in use, the caller blocks until Unlock is called
func (l *SpinLock) Lock() {
for !l.TryLock() {
runtime.Gosched() // interrupt current goroutine execution and allows other goroutines to do some stuff.
}
}
// Unlock will release the spin-lock.
// Calling a Unlock on a spin-lock there is no harmful.
func (l *SpinLock) Unlock() {
atomic.StoreUint32(&l.s, unlocked)
}
// String returns the lock status string literal.
func (l *SpinLock) String() string {
if atomic.LoadUint32(&l.s) == 1 {
return "Locked"
}
return "Unlocked"
}
// New creates an new spin-lock.
func New() sync.Locker {
var lock SpinLock
return &lock
}