mirror of
https://github.com/tursom/GoCollections.git
synced 2025-03-20 22:40:17 +08:00
52 lines
802 B
Go
52 lines
802 B
Go
|
package lock
|
||
|
|
||
|
import (
|
||
|
"github.com/petermattis/goid"
|
||
|
|
||
|
"github.com/tursom/GoCollections/exceptions"
|
||
|
"github.com/tursom/GoCollections/lang/atomic"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
CLH struct {
|
||
|
tail atomic.Reference[clhNode]
|
||
|
state atomic.Reference[clhNode]
|
||
|
}
|
||
|
|
||
|
clhNode struct {
|
||
|
prev *clhNode
|
||
|
locked atomic.Bool
|
||
|
gid int64
|
||
|
}
|
||
|
)
|
||
|
|
||
|
func (c *CLH) Lock() {
|
||
|
node := &clhNode{
|
||
|
prev: c.tail.Load(),
|
||
|
locked: 1, // true
|
||
|
gid: goid.Get(),
|
||
|
}
|
||
|
|
||
|
for !c.tail.CompareAndSwap(node.prev, node) {
|
||
|
node.prev = c.tail.Load()
|
||
|
}
|
||
|
|
||
|
if node.prev == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
for node.prev.locked.Load() {
|
||
|
}
|
||
|
|
||
|
c.state.Store(node)
|
||
|
}
|
||
|
|
||
|
func (c *CLH) Unlock() {
|
||
|
node := c.state.Load()
|
||
|
if node.gid != goid.Get() {
|
||
|
panic(exceptions.NewIllegalAccessException("unlock with wrong goroutine", nil))
|
||
|
}
|
||
|
|
||
|
node.locked.Store(false)
|
||
|
}
|