Initial commit

This commit is contained in:
jdl
2026-06-14 16:58:47 +02:00
parent f0795041e0
commit 8d5f6fc312
4 changed files with 184 additions and 1 deletions

69
keyedmutex.go Normal file
View File

@@ -0,0 +1,69 @@
package keyedmutex
import (
"sync"
)
type keyedLock struct {
lock sync.Mutex
count int
}
type KeyedMutex[K comparable] struct {
mu sync.Mutex
byKey map[K]*keyedLock
}
func New[K comparable]() *KeyedMutex[K] {
return &KeyedMutex[K]{
byKey: map[K]*keyedLock{},
}
}
func (m *KeyedMutex[K]) getLock(key K) *keyedLock {
m.mu.Lock()
defer m.mu.Unlock()
item, ok := m.byKey[key]
if !ok {
item = &keyedLock{}
m.byKey[key] = item
}
item.count++
return item
}
func (m *KeyedMutex[K]) release(key K, unlock bool) {
m.mu.Lock()
defer m.mu.Unlock()
item, ok := m.byKey[key]
if !ok {
panic("unlock of unlocked mutex")
}
item.count--
if unlock {
item.lock.Unlock()
}
if item.count == 0 {
delete(m.byKey, key)
}
}
func (m *KeyedMutex[K]) Lock(key K) {
m.getLock(key).lock.Lock()
}
func (m *KeyedMutex[K]) TryLock(key K) bool {
if ok := m.getLock(key).lock.TryLock(); !ok {
m.release(key, false)
return false
}
return true
}
func (m *KeyedMutex[K]) Unlock(key K) {
m.release(key, true)
}