Skip to content

Instantly share code, notes, and snippets.

@vyzo
Created July 8, 2021 16:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vyzo/b1f6e2922270f6dfcd410a6bb06a88e5 to your computer and use it in GitHub Desktop.
Save vyzo/b1f6e2922270f6dfcd410a6bb06a88e5 to your computer and use it in GitHub Desktop.
Transaction Locks that allow recursive RLocking
#include <pthread.h>
#include <sys/types.h>
u_int64_t goid(void) {
return (u_int64_t)pthread_self();
}
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