Repository navigation
Expand file tree
/
Copy pathsyncmap.go
More file actions
134 lines (116 loc) · 3.81 KB
/
Copy pathsyncmap.go
File metadata and controls
134 lines (116 loc) · 3.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Package syncmap provides a typed, thread-safe map built on top of sync.Map.
package syncmap
import (
"iter"
"sync"
)
// Map provides a thread-safe generic map built on top of sync.Map.
//
// The zero value is ready for use. A Map must not be copied after first use.
type Map[K comparable, V any] struct {
m sync.Map
}
// SyncMap is an alias for Map retained for compatibility.
type SyncMap[K comparable, V any] = Map[K, V]
// NewSyncMap creates a new thread-safe generic map.
func NewSyncMap[K comparable, V any]() *SyncMap[K, V] {
return &Map[K, V]{}
}
// Store sets a key-value pair.
func (sm *Map[K, V]) Store(key K, value V) {
sm.m.Store(key, value)
}
// Load gets a value by key, returning the value and whether it was found.
func (sm *Map[K, V]) Load(key K) (V, bool) {
if val, ok := sm.m.Load(key); ok {
return val.(V), true
}
var zero V
return zero, false
}
// LoadOrStore gets an existing value or stores a new one, returning the actual value and whether it was loaded.
func (sm *Map[K, V]) LoadOrStore(key K, value V) (V, bool) {
actual, loaded := sm.m.LoadOrStore(key, value)
return actual.(V), loaded
}
// LoadAndDelete gets an existing value and deletes it, returning the value and whether it was loaded.
func (sm *Map[K, V]) LoadAndDelete(key K) (V, bool) {
val, loaded := sm.m.LoadAndDelete(key)
if loaded {
return val.(V), true
}
var zero V
return zero, false
}
// Delete removes a key.
func (sm *Map[K, V]) Delete(key K) {
sm.m.Delete(key)
}
// Clear deletes all entries.
func (sm *Map[K, V]) Clear() {
sm.m.Clear()
}
// Swap swaps the value for a key and returns the previous value if any.
// The loaded result reports whether the key was present.
func (sm *Map[K, V]) Swap(key K, value V) (previous V, loaded bool) {
prev, loaded := sm.m.Swap(key, value)
if loaded {
return prev.(V), true
}
var zero V
return zero, false
}
// CompareAndSwap swaps the old and new values for key if the value stored in the map is equal to old.
// It panics if old is not comparable, matching sync.Map.
func (sm *Map[K, V]) CompareAndSwap(key K, old V, new V) (swapped bool) {
return sm.m.CompareAndSwap(key, old, new)
}
// CompareAndDelete deletes the entry for key if its value is equal to old.
// It panics if old is not comparable, matching sync.Map.
func (sm *Map[K, V]) CompareAndDelete(key K, old V) (deleted bool) {
return sm.m.CompareAndDelete(key, old)
}
// All returns an iterator over the keys and values in the map.
// All does not necessarily observe a consistent snapshot when the map is modified concurrently.
func (sm *Map[K, V]) All() iter.Seq2[K, V] {
return func(yield func(K, V) bool) {
sm.m.Range(func(key, value any) bool {
return yield(key.(K), value.(V))
})
}
}
// Range calls fn sequentially for each key-value pair. Returning false stops the iteration.
// Range does not necessarily observe a consistent snapshot when the map is modified concurrently.
func (sm *Map[K, V]) Range(fn func(key K, value V) bool) {
sm.All()(fn)
}
// Keys returns the keys encountered during one Range call.
// It does not return a consistent snapshot when the map is modified concurrently.
func (sm *Map[K, V]) Keys() []K {
var keys []K
sm.Range(func(key K, value V) bool {
keys = append(keys, key)
return true
})
return keys
}
// Values returns the values encountered during one Range call.
// It does not return a consistent snapshot when the map is modified concurrently.
func (sm *Map[K, V]) Values() []V {
var values []V
sm.Range(func(key K, value V) bool {
values = append(values, value)
return true
})
return values
}
// Len returns the number of keys encountered during one Range call in O(N) time.
// It does not return a consistent snapshot when the map is modified concurrently.
func (sm *Map[K, V]) Len() int {
count := 0
sm.Range(func(key K, value V) bool {
count++
return true
})
return count
}