Created
July 8, 2021 16:54
-
-
Save vyzo/b1f6e2922270f6dfcd410a6bb06a88e5 to your computer and use it in GitHub Desktop.
Transaction Locks that allow recursive RLocking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
#include <sys/types.h> | |
u_int64_t goid(void) { | |
return (u_int64_t)pthread_self(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package splitstore | |
import ( | |
"C" | |
"runtime" | |
"sync" | |
) | |
// A TxnLock is like a RWMutex but it allows recursive RLocking. | |
// This is necessary to support Views that can recursively operate on the blockstore without deadlock. | |
type TxnLock struct { | |
rwlk sync.RWMutex | |
mx sync.Mutex | |
views map[uint64]int | |
} | |
// I will go to hell | |
func goid() uint64 | |
func (l *TxnLock) Init() { | |
l.views = make(map[uint64]int) | |
} | |
func (l *TxnLock) RLock() { | |
runtime.LockOSThread() | |
self := goid() | |
l.mx.Lock() | |
count := l.views[self] | |
count++ | |
l.views[self] = count | |
l.mx.Unlock() | |
if count > 1 { | |
return | |
} | |
l.rwlk.RLock() | |
} | |
func (l *TxnLock) RUnlock() { | |
defer runtime.UnlockOSThread() | |
self := goid() | |
l.mx.Lock() | |
count := l.views[self] | |
count-- | |
l.views[self] = count | |
l.mx.Unlock() | |
if count > 0 { | |
return | |
} | |
l.rwlk.RUnlock() | |
} | |
func (l *TxnLock) Lock() { | |
l.rwlk.Lock() | |
} | |
func (l *TxnLock) Unlock() { | |
l.rwlk.Unlock() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment