From b687d8ea9589f0ffa54e38df68f19bb8f91f59dc Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 18 Feb 2024 22:22:18 +0100 Subject: [PATCH] Create a concurrent map --- transcoder/src/cmap.go | 56 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 transcoder/src/cmap.go 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) +}