95 lines
1.9 KiB
Go
95 lines
1.9 KiB
Go
package app
|
|
|
|
import (
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
type transportIfaceOrchestrator struct {
|
|
mu sync.Mutex
|
|
locks map[string]*sync.Mutex
|
|
}
|
|
|
|
var transportIfaceRuntime = newTransportIfaceOrchestrator()
|
|
|
|
func newTransportIfaceOrchestrator() *transportIfaceOrchestrator {
|
|
return &transportIfaceOrchestrator{
|
|
locks: map[string]*sync.Mutex{},
|
|
}
|
|
}
|
|
|
|
func (o *transportIfaceOrchestrator) lockFor(ifaceID string) *sync.Mutex {
|
|
key := normalizeTransportIfaceID(ifaceID)
|
|
o.mu.Lock()
|
|
defer o.mu.Unlock()
|
|
if m, ok := o.locks[key]; ok {
|
|
return m
|
|
}
|
|
m := &sync.Mutex{}
|
|
o.locks[key] = m
|
|
return m
|
|
}
|
|
|
|
func withTransportIfaceLock(ifaceID string, fn func()) {
|
|
m := transportIfaceRuntime.lockFor(ifaceID)
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
fn()
|
|
}
|
|
|
|
func withTransportIfaceLocks(ifaceIDs []string, fn func()) {
|
|
ids := normalizeTransportIfaceLockIDs(ifaceIDs)
|
|
if len(ids) == 0 {
|
|
fn()
|
|
return
|
|
}
|
|
locks := make([]*sync.Mutex, 0, len(ids))
|
|
for _, ifaceID := range ids {
|
|
locks = append(locks, transportIfaceRuntime.lockFor(ifaceID))
|
|
}
|
|
for _, m := range locks {
|
|
m.Lock()
|
|
}
|
|
defer func() {
|
|
for i := len(locks) - 1; i >= 0; i-- {
|
|
locks[i].Unlock()
|
|
}
|
|
}()
|
|
fn()
|
|
}
|
|
|
|
func normalizeTransportIfaceLockIDs(ifaceIDs []string) []string {
|
|
if len(ifaceIDs) == 0 {
|
|
return nil
|
|
}
|
|
seen := map[string]struct{}{}
|
|
out := make([]string, 0, len(ifaceIDs))
|
|
for _, raw := range ifaceIDs {
|
|
id := normalizeTransportIfaceID(raw)
|
|
if _, ok := seen[id]; ok {
|
|
continue
|
|
}
|
|
seen[id] = struct{}{}
|
|
out = append(out, id)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
func resolveTransportClientIfaceID(clientID string) (string, bool) {
|
|
id := sanitizeID(clientID)
|
|
if id == "" {
|
|
return "", false
|
|
}
|
|
transportMu.Lock()
|
|
st := loadTransportClientsState()
|
|
idx := findTransportClientIndex(st.Items, id)
|
|
if idx < 0 {
|
|
transportMu.Unlock()
|
|
return "", false
|
|
}
|
|
ifaceID := normalizeTransportIfaceID(st.Items[idx].IfaceID)
|
|
transportMu.Unlock()
|
|
return ifaceID, true
|
|
}
|