diff --git a/transcoder/src/cmap.go b/transcoder/src/cmap.go new file mode 100644 index 00000000..e10447cf --- /dev/null +++ b/transcoder/src/cmap.go @@ -0,0 +1,56 @@ +package src + +import "sync" + +type CMap[K comparable, V any] struct { + data map[K]V + lock sync.RWMutex +} + +func NewCMap[K comparable, V any]() CMap[K, V] { + return CMap[K, V]{ + data: make(map[K]V), + } +} + +func (m *CMap[K, V]) Get(key K) (V, bool) { + m.lock.RLock() + defer m.lock.RUnlock() + ret, ok := m.data[key] + return ret, ok +} + +func (m *CMap[K, V]) GetOrCreate(key K, create func() V) (V, bool) { + m.lock.RLock() + ret, ok := m.data[key] + if ok { + m.lock.RUnlock() + return ret, false + } + m.lock.RUnlock() + + // data does not exist, create it + m.lock.Lock() + defer m.lock.Unlock() + + // check if another gorountine already created it before we could lock + ret, ok = m.data[key] + if ok { + return ret, false + } + + val := create() + m.data[key] = val + return val, true +} + +func (m *CMap[K, V]) GetOrSet(key K, val V) (V, bool) { + return m.GetOrCreate(key, func() V { return val }) +} + +func (m *CMap[K, V]) Remove(key K) { + m.lock.Lock() + defer m.lock.Unlock() + + delete(m.data, key) +}