ants/internal/spinlock.go

38 lines
761 B
Go
Raw Permalink Normal View History

2021-05-18 10:43:13 +03:00
// Copyright 2019 Andy Pan & Dietoad. All rights reserved.
2019-09-27 15:51:46 +03:00
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
2019-10-04 06:24:13 +03:00
package internal
2019-09-27 15:51:46 +03:00
import (
"runtime"
"sync"
"sync/atomic"
)
type spinLock uint32
const maxBackoff = 16
2019-09-27 15:51:46 +03:00
func (sl *spinLock) Lock() {
2021-05-18 10:43:13 +03:00
backoff := 1
2019-09-27 15:51:46 +03:00
for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
// Leverage the exponential backoff algorithm, see https://en.wikipedia.org/wiki/Exponential_backoff.
2021-05-18 10:43:13 +03:00
for i := 0; i < backoff; i++ {
runtime.Gosched()
}
if backoff < maxBackoff {
backoff <<= 1
}
2019-09-27 15:51:46 +03:00
}
}
func (sl *spinLock) Unlock() {
atomic.StoreUint32((*uint32)(sl), 0)
}
2019-10-04 06:24:13 +03:00
// NewSpinLock instantiates a spin-lock.
func NewSpinLock() sync.Locker {
2019-09-27 15:51:46 +03:00
return new(spinLock)
}