-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmap.go
158 lines (144 loc) · 3.72 KB
/
map.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
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package ash
import (
"sync/atomic"
)
// Map is a drop-in replacement for sync.Map backed by skip list.
// Use &ash.Map{*SkipList} or new(ash.Map).From(ash.NewSkipList(maxlevel)) to instantiate.
type Map struct {
*SkipList
}
func (m *Map) From(sl *SkipList) *Map {
m.SkipList = sl
return m
}
// Clear deletes all the entries, resulting in an empty Map.
func (m *Map) Clear() {
for level := int(atomic.LoadUint64(&m.SkipList.topLevel) - 1); level >= 0; level-- {
m.SkipList.start.tower.UpdateNext(level, nil)
}
}
// CompareAndDelete deletes the entry for key if its value is equal to old.
// The old value must be of a comparable type.
//
// If there is no current value for key in the map, CompareAndDelete
// returns false (even if the old value is the nil interface value).
func (m *Map) CompareAndDelete(key, old any) (deleted bool) {
keyHash := HashFunc(key)
nd := m.SkipList.Search(keyHash)
if nd == nil {
return
}
val := nd.GetVal()
if val == nil || val != old {
return
}
m.Delete(key)
deleted = true
return
}
// CompareAndSwap swaps the old and new values for key
// if the value stored in the map is equal to old.
// The old value must be of a comparable type.
func (m *Map) CompareAndSwap(key, old, new any) (swapped bool) {
hKey := HashFunc(key)
for {
nd := m.SkipList.Search(hKey)
if nd == nil {
return
}
val := nd.GetVal()
if val != old {
return
}
if !nd.SwapVal(val, new) {
continue
}
swapped = true
break
}
return
}
// Delete deletes the value for a key.
func (m *Map) Delete(key any) {
hKey := HashFunc(key)
m.SkipList.Delete(hKey)
}
// Load returns the value stored in the map for a key, or nil if no value is present.
// The ok result indicates whether value was found in the map.
func (m *Map) Load(key any) (value any, ok bool) {
hKey := HashFunc(key)
nd := m.SkipList.Search(hKey)
if nd == nil {
return nil, false
}
val := nd.GetVal()
return val, ok
}
// LoadAndDelete deletes the value for a key, returning the previous value if any.
// The loaded result reports whether the key was present.
func (m *Map) LoadAndDelete(key any) (value any, loaded bool) {
hKey := HashFunc(key)
nd, _ := m.SkipList.Delete(hKey)
if nd == nil {
return
}
return nd.GetVal(), true
}
// LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns
// the given value. The loaded result is true if the given value was loaded, false if stored.
func (m *Map) LoadOrStore(key, value any) (actual any, loaded bool) {
hKey := HashFunc(key)
nd := m.SkipList.Search(hKey)
if nd != nil {
actual = nd.GetVal()
loaded = true
return
}
m.SkipList.Store(hKey, value)
actual = value
return
}
// Store sets the value for a key.
func (m *Map) Store(key, value any) {
hKey := HashFunc(key)
m.SkipList.Store(hKey, value)
}
// Range calls f sequentially for each key and value present in the map.
// If f returns false, range stops the iteration.
func (m *Map) Range(f func(key, value any) bool) {
// iterate through items at the bottom level
for next := m.SkipList.start.Next(0); next != nil; next = next.Next(0) {
if !f(next.key, next.GetVal()) {
return
}
}
}
// Len reports the number of stored keys
func (m *Map) Len() (l int) {
next := m.SkipList.start.Next(0)
for next != nil {
l++
next = next.Next(0)
}
return
}
// Swap returns the value for a key and returns the previous value if any.
// The loaded result reports whether the key was present.
func (m *Map) Swap(key, value any) (previous any, loaded bool) {
hKey := HashFunc(key)
for {
nd := m.SkipList.Search(hKey)
if nd == nil {
m.SkipList.Store(hKey, value)
return
}
previous = nd.GetVal()
if !nd.SwapVal(previous, value) {
previous = nil
continue
}
loaded = true
break
}
return
}