GoCollections/concurrent/ReentrantLock.go
2022-03-23 14:28:41 +08:00

55 lines
942 B
Go

package concurrent
import (
"fmt"
"github.com/tursom/GoCollections/exceptions"
"sync"
)
type ReentrantLock struct {
lock sync.Mutex
cond sync.Cond
recursion int32
host int64
}
func NewReentrantLock() *ReentrantLock {
res := &ReentrantLock{
recursion: 0,
host: 0,
}
res.cond = *sync.NewCond(&res.lock)
return res
}
func (rt *ReentrantLock) Lock() {
id := GetGoroutineID()
rt.lock.Lock()
defer rt.lock.Unlock()
if rt.host == id {
rt.recursion++
return
}
for rt.recursion != 0 {
rt.cond.Wait()
}
rt.host = id
rt.recursion = 1
}
func (rt *ReentrantLock) Unlock() {
rt.lock.Lock()
defer rt.lock.Unlock()
if rt.recursion == 0 || rt.host != GetGoroutineID() {
panic(exceptions.NewWrongCallHostException(fmt.Sprintf("the wrong call host: (%d); current_id: %d; recursion: %d", rt.host, GetGoroutineID(), rt.recursion)))
}
rt.recursion--
if rt.recursion == 0 {
rt.cond.Signal()
}
}