Files
tasks/common/locks/id_mutex.go
Stephan BehnkeandGitHub c9e360a3fb go fix (#9337)
## What changed?

Integrate Go 1.26's new `go fix` into workflow.

NOTE that the changes caused our linter to fire; a [separate
commit](https://github.com/temporalio/temporal/pull/9337/commits/1b23f787aef370098b35829c4d17dcc06230b4c1)
addresses those.

## Why?

Ensure Go code is standardized/modernized.

## How did you test it?
- [ ] built
- [ ] run locally and tested manually
- [x] covered by existing tests
- [ ] added new unit test(s)
- [ ] added new functional test(s)
2026-02-18 09:12:19 -08:00

103 lines
2.1 KiB
Go

package locks
import (
"sync"
)
type (
// HashFunc represents a hash function for string
HashFunc func(any) uint32
// IDMutex is an interface which can lock on specific comparable identifier
IDMutex interface {
LockID(identifier any)
UnlockID(identifier any)
}
// idMutexShardImpl is the implementation of IDMutex shard
idMutexImpl struct {
numShard uint32
hashFn HashFunc
shards map[uint32]*idMutexShardImpl
}
// idMutexShardImpl is the implementation of IDMutex shard
idMutexShardImpl struct {
sync.Mutex
mutexInfos map[any]*mutexInfo
}
mutexInfo struct {
// how many caller are using this lock info, including the
// the caller already have the lock
// this is guarded by lock in idLockImpl
waitCount int
// actual lock
sync.Mutex
}
)
// NewIDMutex create a new IDLock
func NewIDMutex(numShard uint32, hashFn HashFunc) IDMutex {
impl := &idMutexImpl{
numShard: numShard,
hashFn: hashFn,
shards: make(map[uint32]*idMutexShardImpl),
}
for i := range numShard {
impl.shards[i] = &idMutexShardImpl{
mutexInfos: make(map[any]*mutexInfo),
}
}
return impl
}
func newMutexInfo() *mutexInfo {
return &mutexInfo{
waitCount: 1,
}
}
// LockID lock by specific identifier
func (idMutex *idMutexImpl) LockID(identifier any) {
shard := idMutex.shards[idMutex.getShardIndex(identifier)]
shard.Lock()
mutexInfo, ok := shard.mutexInfos[identifier]
if !ok {
mutexInfo := newMutexInfo()
shard.mutexInfos[identifier] = mutexInfo
shard.Unlock()
mutexInfo.Lock()
return
}
mutexInfo.waitCount++
shard.Unlock()
mutexInfo.Lock()
}
// UnlockID unlock by specific identifier
func (idMutex *idMutexImpl) UnlockID(identifier any) {
shard := idMutex.shards[idMutex.getShardIndex(identifier)]
shard.Lock()
defer shard.Unlock()
mutexInfo, ok := shard.mutexInfos[identifier]
if !ok {
panic("cannot find workflow lock")
}
mutexInfo.Unlock()
if mutexInfo.waitCount == 1 {
delete(shard.mutexInfos, identifier)
} else {
mutexInfo.waitCount--
}
}
func (idMutex *idMutexImpl) getShardIndex(key any) uint32 {
return idMutex.hashFn(key) % idMutex.numShard
}