104 lines
2.4 KiB
Go
104 lines
2.4 KiB
Go
|
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.
|
||
|
func (m *Map[K, V]) Do(f func(m map[K]V)) {
|
||
|
m.mutex.Lock()
|
||
|
defer m.mutex.Unlock()
|
||
|
f(m.data)
|
||
|
}
|