32 lines
797 B
Go
32 lines
797 B
Go
package locks
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
// Number of lock shards for reducing contention
|
|
const NumLockShards = 32
|
|
|
|
// GetShardIndex returns the shard index for a given key using FNV-1a hash
|
|
func GetShardIndex(key string) int {
|
|
// Use FNV-1a hash for good distribution
|
|
var h uint32 = 2166136261 // FNV offset basis
|
|
for i := 0; i < len(key); i++ {
|
|
h ^= uint32(key[i])
|
|
h *= 16777619 // FNV prime
|
|
}
|
|
return int(h % NumLockShards)
|
|
}
|
|
|
|
// GetKeyLock returns a lock for the given key using sharding
|
|
func GetKeyLock(keyLocks []sync.Map, key string) *sync.RWMutex {
|
|
shardIndex := GetShardIndex(key)
|
|
shard := &keyLocks[shardIndex]
|
|
|
|
keyLock, _ := shard.LoadOrStore(key, &sync.RWMutex{})
|
|
if rl, ok := keyLock.(*sync.RWMutex); ok {
|
|
return rl
|
|
}
|
|
panic("corrupted lock shard: expected *sync.RWMutex")
|
|
}
|