aerc/lib/uidstore/uidstore.go

63 lines
1.5 KiB
Go

// Package uidstore provides a concurrency-safe two-way mapping between UIDs
// used by the UI and arbitrary string keys as used by different mail backends.
//
// Multiple Store instances can safely be created and the UIDs that they
// generate will be globally unique.
package uidstore
import (
"sync"
"sync/atomic"
)
var nextUID uint32 = 1
// Store holds a mapping between application keys and globally-unique UIDs.
type Store struct {
keyByUID map[uint32]string
uidByKey map[string]uint32
m sync.Mutex
}
// NewStore creates a new, empty Store.
func NewStore() *Store {
return &Store{
keyByUID: make(map[uint32]string),
uidByKey: make(map[string]uint32),
}
}
// GetOrInsert returns the UID for the provided key. If the key was already
// present in the store, the same UID value is returned. Otherwise, the key is
// inserted and the newly generated UID is returned.
func (s *Store) GetOrInsert(key string) uint32 {
s.m.Lock()
defer s.m.Unlock()
if uid, ok := s.uidByKey[key]; ok {
return uid
}
uid := atomic.AddUint32(&nextUID, 1)
s.keyByUID[uid] = key
s.uidByKey[key] = uid
return uid
}
// GetKey returns the key for the provided UID, if available.
func (s *Store) GetKey(uid uint32) (string, bool) {
s.m.Lock()
defer s.m.Unlock()
key, ok := s.keyByUID[uid]
return key, ok
}
// RemoveUID removes the specified UID from the store.
func (s *Store) RemoveUID(uid uint32) {
s.m.Lock()
defer s.m.Unlock()
key, ok := s.keyByUID[uid]
if ok {
delete(s.uidByKey, key)
}
delete(s.keyByUID, uid)
}