5e5a81bf23
* add go linter - "unused" * use _ to name unused but needed padding variable * remove unused code * add queue test to appease unused linter * remove unused code in test * remove unused func * remove unused struct identified by linter * remove unused variable * remove unused code * remove unused file * remove unused struct * remove unused function * remove unused observe peers function in raft * remove unused declareFaults function * annotate nolint:unused on needed methods
76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
package shardedmutex
|
|
|
|
import (
|
|
"hash/maphash"
|
|
"sync"
|
|
)
|
|
|
|
const cacheline = 64
|
|
|
|
// padding a mutex to a cacheline improves performance as the cachelines are not contested
|
|
// name old time/op new time/op delta
|
|
// Locks-8 74.6ns ± 7% 12.3ns ± 2% -83.54% (p=0.000 n=20+18)
|
|
type paddedMutex struct {
|
|
mt sync.Mutex
|
|
_ [cacheline - 8]uint8
|
|
}
|
|
|
|
type ShardedMutex struct {
|
|
shards []paddedMutex
|
|
}
|
|
|
|
// New creates a new ShardedMutex with N shards
|
|
func New(nShards int) ShardedMutex {
|
|
if nShards < 1 {
|
|
panic("n_shards cannot be less than 1")
|
|
}
|
|
return ShardedMutex{
|
|
shards: make([]paddedMutex, nShards),
|
|
}
|
|
}
|
|
|
|
func (sm ShardedMutex) Shards() int {
|
|
return len(sm.shards)
|
|
}
|
|
|
|
func (sm ShardedMutex) Lock(shard int) {
|
|
sm.shards[shard].mt.Lock()
|
|
}
|
|
|
|
func (sm ShardedMutex) Unlock(shard int) {
|
|
sm.shards[shard].mt.Unlock()
|
|
}
|
|
|
|
func (sm ShardedMutex) GetLock(shard int) sync.Locker {
|
|
return &sm.shards[shard].mt
|
|
}
|
|
|
|
type ShardedMutexFor[K any] struct {
|
|
inner ShardedMutex
|
|
|
|
hasher func(maphash.Seed, K) uint64
|
|
seed maphash.Seed
|
|
}
|
|
|
|
func NewFor[K any](hasher func(maphash.Seed, K) uint64, nShards int) ShardedMutexFor[K] {
|
|
return ShardedMutexFor[K]{
|
|
inner: New(nShards),
|
|
hasher: hasher,
|
|
seed: maphash.MakeSeed(),
|
|
}
|
|
}
|
|
|
|
func (sm ShardedMutexFor[K]) shardFor(key K) int {
|
|
return int(sm.hasher(sm.seed, key) % uint64(len(sm.inner.shards)))
|
|
}
|
|
|
|
func (sm ShardedMutexFor[K]) Lock(key K) {
|
|
sm.inner.Lock(sm.shardFor(key))
|
|
}
|
|
func (sm ShardedMutexFor[K]) Unlock(key K) {
|
|
sm.inner.Unlock(sm.shardFor(key))
|
|
}
|
|
func (sm ShardedMutexFor[K]) GetLock(key K) sync.Locker {
|
|
return sm.inner.GetLock(sm.shardFor(key))
|
|
}
|