github.com/tursom/GoCollections@v0.3.10/concurrent/ReentrantLock.go (about) 1 /* 2 * Copyright (c) 2022 tursom. All rights reserved. 3 * Use of this source code is governed by a GPL-3 4 * license that can be found in the LICENSE file. 5 */ 6 7 package concurrent 8 9 import ( 10 "fmt" 11 "sync" 12 13 "github.com/tursom/GoCollections/exceptions" 14 ) 15 16 type ReentrantLock struct { 17 lock sync.Mutex 18 cond sync.Cond 19 recursion int32 20 host int64 21 } 22 23 func NewReentrantLock() *ReentrantLock { 24 res := &ReentrantLock{ 25 recursion: 0, 26 host: 0, 27 } 28 res.cond = *sync.NewCond(&res.lock) 29 return res 30 } 31 32 func (rt *ReentrantLock) TryLock() bool { 33 id := GetGoroutineID() 34 rt.lock.Lock() 35 defer rt.lock.Unlock() 36 37 if rt.host == id { 38 rt.recursion++ 39 return true 40 } 41 42 if rt.recursion == 0 { 43 rt.host = id 44 rt.recursion = 1 45 return true 46 } 47 48 return false 49 } 50 51 func (rt *ReentrantLock) Lock() { 52 id := GetGoroutineID() 53 rt.lock.Lock() 54 defer rt.lock.Unlock() 55 56 if rt.host == id { 57 rt.recursion++ 58 return 59 } 60 61 for rt.recursion != 0 { 62 rt.cond.Wait() 63 } 64 rt.host = id 65 rt.recursion = 1 66 } 67 68 func (rt *ReentrantLock) Unlock() { 69 rt.lock.Lock() 70 defer rt.lock.Unlock() 71 72 if rt.recursion == 0 || rt.host != GetGoroutineID() { 73 panic(exceptions.NewWrongCallHostException(fmt.Sprintf("the wrong call host: (%d); current_id: %d; recursion: %d", rt.host, GetGoroutineID(), rt.recursion))) 74 } 75 76 rt.recursion-- 77 if rt.recursion == 0 { 78 rt.cond.Signal() 79 } 80 }