mirror of
https://github.com/tursom/GoCollections.git
synced 2025-02-16 13:40:09 +08:00
72 lines
1.2 KiB
Go
72 lines
1.2 KiB
Go
package concurrent
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/tursom/GoCollections/exceptions"
|
|
"sync"
|
|
)
|
|
|
|
type ReentrantRWLock struct {
|
|
lock sync.Mutex
|
|
rlock sync.RWMutex
|
|
cond sync.Cond
|
|
recursion int32
|
|
host int64
|
|
}
|
|
|
|
func NewReentrantRWLock() *ReentrantRWLock {
|
|
res := &ReentrantRWLock{
|
|
recursion: 0,
|
|
host: 0,
|
|
}
|
|
res.cond = *sync.NewCond(&res.lock)
|
|
return res
|
|
}
|
|
|
|
func (rt *ReentrantRWLock) 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
|
|
rt.rlock.Lock()
|
|
}
|
|
|
|
func (rt *ReentrantRWLock) 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.rlock.Unlock()
|
|
rt.cond.Signal()
|
|
}
|
|
}
|
|
|
|
func (rt *ReentrantRWLock) RLock() {
|
|
if rt.host == GetGoroutineID() {
|
|
return
|
|
}
|
|
rt.rlock.RLock()
|
|
}
|
|
|
|
func (rt *ReentrantRWLock) RUnlock() {
|
|
if rt.host == GetGoroutineID() {
|
|
return
|
|
}
|
|
rt.rlock.RUnlock()
|
|
}
|