FILE / ScuroNeko/Laniakea

scene_locks.go

Исходный файл и его история в репозитории.
FILE f03a081ed6ad0d7aa86944cacb94ff61573c29bd
Files
Laniakea/scene_locks.go
T
ScuroNeko f03a081ed6
Golang lint / lint (pull_request) Successful in 1m20s
Golang lint / lint (push) Successful in 4m8s
(new): rich message support
(fix): runtime reliability
(tests): regression coverage
(doc): v1.1 release notes
2026-08-12 16:34:44 +03:00

81 lines
1.5 KiB
Go

package laniakea
import (
"sort"
"sync"
)
type sceneLockEntry struct {
mu sync.Mutex
refs int
}
type sceneKeyLocker struct {
mu sync.Mutex
entries map[string]*sceneLockEntry
}
func (l *sceneKeyLocker) lock(keys []string) func() {
keys = uniqueSortedStrings(keys)
if len(keys) == 0 {
return func() {}
}
l.mu.Lock()
if l.entries == nil {
l.entries = make(map[string]*sceneLockEntry)
}
entries := make([]*sceneLockEntry, len(keys))
for i, key := range keys {
entry := l.entries[key]
if entry == nil {
entry = new(sceneLockEntry)
l.entries[key] = entry
}
entry.refs++
entries[i] = entry
}
l.mu.Unlock()
for _, entry := range entries {
entry.mu.Lock()
}
return func() {
for i := len(entries) - 1; i >= 0; i-- {
entries[i].mu.Unlock()
}
l.mu.Lock()
for i, key := range keys {
entries[i].refs--
if entries[i].refs == 0 {
delete(l.entries, key)
}
}
l.mu.Unlock()
}
}
func uniqueSortedStrings(values []string) []string {
sort.Strings(values)
result := values[:0]
for _, value := range values {
if value == "" || len(result) > 0 && result[len(result)-1] == value {
continue
}
result = append(result, value)
}
return result
}
func sceneKeysForContext(ctx *MessageContext) []string {
keys := make([]string, 0, 3)
for _, scope := range []SceneScope{SceneScopeUserChat, SceneScopeChat, SceneScopeUser} {
if key, ok := buildSceneKey(scope, ctx); ok {
keys = append(keys, key)
}
}
return keys
}