GoCollections/concurrent/lock/CLH.go

52 lines
802 B
Go
Raw Normal View History

2023-03-15 13:59:26 +08:00
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)
}