-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsyncmap.go
98 lines (79 loc) · 1.97 KB
/
syncmap.go
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
package goutil
import "sync"
type SyncMap[K Hashable, V any] struct {
value map[K]V
hasVal map[K]bool
mu sync.Mutex
null V
}
// NewMap creates a new synchronized map that uses sync.Mutex behind the scenes
func NewMap[K Hashable, V any]() *SyncMap[K, V] {
return &SyncMap[K, V]{
value: map[K]V{},
hasVal: map[K]bool{},
}
}
// Get returns a value or an error if it exists
func (syncmap *SyncMap[K, V]) Get(key K) (V, bool) {
syncmap.mu.Lock()
defer syncmap.mu.Unlock()
if hasVal, ok := syncmap.hasVal[key]; !ok || !hasVal {
return syncmap.null, false
}else if val, ok := syncmap.value[key]; ok {
return val, true
}
return syncmap.null, false
}
// Set sets or adds a new key with a value
func (syncmap *SyncMap[K, V]) Set(key K, value V) {
syncmap.mu.Lock()
defer syncmap.mu.Unlock()
syncmap.value[key] = value
syncmap.hasVal[key] = true
}
// Del removes an item by key
func (syncmap *SyncMap[K, V]) Del(key K){
syncmap.mu.Lock()
defer syncmap.mu.Unlock()
delete(syncmap.value, key)
delete(syncmap.hasVal, key)
}
// Has returns true if a key value exists in the list
func (syncmap *SyncMap[K, V]) Has(key K) bool {
syncmap.mu.Lock()
defer syncmap.mu.Unlock()
if hasVal, ok := syncmap.hasVal[key]; !ok || !hasVal {
return false
}else if _, ok := syncmap.value[key]; ok {
return true
}
return false
}
// ForEach runs a callback function for each key value pair
//
// in the callback, return true to continue, and false to break the loop
func (syncmap *SyncMap[K, V]) ForEach(cb func(key K, value V) bool){
syncmap.mu.Lock()
keyList := []K{}
for key := range syncmap.value {
keyList = append(keyList, key)
}
syncmap.mu.Unlock()
for _, key := range keyList {
syncmap.mu.Lock()
if hasVal, ok := syncmap.hasVal[key]; !ok || !hasVal {
delete(syncmap.value, key)
delete(syncmap.hasVal, key)
syncmap.mu.Unlock()
continue
}
var val V
if v, ok := syncmap.value[key]; ok {
val = v
}
syncmap.mu.Unlock()
if !cb(key, val) {
break
}
}
}