initial commit

This commit is contained in:
Milarin 2024-02-15 15:57:41 +01:00
commit 6f48f8af8f
2 changed files with 122 additions and 0 deletions

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module git.milar.in/milarin/cmap
go 1.22.0

119
map.go Normal file
View File

@ -0,0 +1,119 @@
package cmap
import "sync"
// Map represents a map safe for concurrent use
type Map[K comparable, V any] struct {
mutex sync.RWMutex
data map[K]V
}
// New creates a new generic Map
func New[K comparable, V any]() *Map[K, V] {
return &Map[K, V]{data: map[K]V{}}
}
// Put puts the key-value pair into m
func (m *Map[K, V]) Put(key K, value V) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.data[key] = value
}
// GetHas returns the corresponding value for the given key in m
// as well as a bool indicating if a value was present at all
func (m *Map[K, V]) GetHas(key K) (V, bool) {
m.mutex.RLock()
defer m.mutex.RUnlock()
value, ok := m.data[key]
return value, ok
}
// Get returns the corresponding value for the given key in m
func (m *Map[K, V]) Get(key K) V {
value, _ := m.GetHas(key)
return value
}
// Has returns a bool indicating if a value was present for the given key
func (m *Map[K, V]) Has(key K) bool {
_, ok := m.GetHas(key)
return ok
}
// Delete deletes the key-value pair from m
func (m *Map[K, V]) Delete(key K) {
m.mutex.Lock()
defer m.mutex.Unlock()
delete(m.data, key)
}
// Count returns the amount of key-value pairs currently stored in m
func (m *Map[K, V]) Count() int {
m.mutex.RLock()
defer m.mutex.RUnlock()
return len(m.data)
}
// Iter calls f for every key-value pair stored in m.
// Be aware that this locks m for write access
// as pointer types could be modified in f
func (m *Map[K, V]) Iter(f func(key K, value V)) {
m.mutex.Lock()
defer m.mutex.Unlock()
for key, value := range m.data {
f(key, value)
}
}
// Keys returns a slice containing all currently stored keys in m.
// Pointer values are returned as they were received
func (m *Map[K, V]) Keys() []K {
m.mutex.RLock()
defer m.mutex.RUnlock()
keys := make([]K, 0, len(m.data))
for key := range m.data {
keys = append(keys, key)
}
return keys
}
// Values returns a slice containing all currently stored values in m.
// Pointer values are returned as they were received
func (m *Map[K, V]) Values() []V {
m.mutex.RLock()
defer m.mutex.RUnlock()
values := make([]V, 0, len(m.data))
for _, value := range m.data {
values = append(values, value)
}
return values
}
// Do calls f with the underlying primitive map.
// Be aware that this locks m for write access
// so Do can be used for reading as well as modifiying m.
// After f returns, the map will be shallow-copied in order to prevent
// clueless programmers from storing the map and modifying it afterwards.
// If you need that little bit of optimization, use DoUnsafe instead
func (m *Map[K, V]) Do(f func(m map[K]V)) {
m.mutex.Lock()
defer m.mutex.Unlock()
f(m.data)
nm := map[K]V{}
for key, value := range m.data {
nm[key] = value
}
m.data = nm
}
// DoUnsafe behaves like Do but does not create a shallow-copy of m
func (m *Map[K, V]) DoUnsafe(f func(m map[K]V)) {
m.mutex.Lock()
defer m.mutex.Unlock()
f(m.data)
}