Skip to content

Commit 008e0d2

Browse files
committed
Add MutexMap MutexSection/RMutexSection
1 parent 4f59501 commit 008e0d2

File tree

1 file changed

+119
-41
lines changed

1 file changed

+119
-41
lines changed

mutex_map.go

Lines changed: 119 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,53 +2,43 @@ package nex
22

33
import "sync"
44

5+
// RawMap implements a map type with helper functions to operate it.
6+
type RawMap[K comparable, V any] struct {
7+
real map[K]V
8+
}
9+
510
// MutexMap implements a map type with go routine safe accessors through mutex locks. Embeds sync.RWMutex
611
type MutexMap[K comparable, V any] struct {
7-
*sync.RWMutex
8-
real map[K]V
12+
mutex *sync.RWMutex
13+
rawMap RawMap[K, V]
914
}
1015

1116
// Set sets a key to a given value
12-
func (m *MutexMap[K, V]) Set(key K, value V) {
13-
m.Lock()
14-
defer m.Unlock()
15-
17+
func (m *RawMap[K, V]) Set(key K, value V) {
1618
m.real[key] = value
1719
}
1820

1921
// Get returns the given key value and a bool if found
20-
func (m *MutexMap[K, V]) Get(key K) (V, bool) {
21-
m.RLock()
22-
defer m.RUnlock()
23-
22+
func (m *RawMap[K, V]) Get(key K) (V, bool) {
2423
value, ok := m.real[key]
2524

2625
return value, ok
2726
}
2827

2928
// Has checks if a key exists in the map
30-
func (m *MutexMap[K, V]) Has(key K) bool {
31-
m.RLock()
32-
defer m.RUnlock()
33-
29+
func (m *RawMap[K, V]) Has(key K) bool {
3430
_, ok := m.real[key]
3531
return ok
3632
}
3733

3834
// Delete removes a key from the internal map
39-
func (m *MutexMap[K, V]) Delete(key K) {
40-
m.Lock()
41-
defer m.Unlock()
42-
35+
func (m *RawMap[K, V]) Delete(key K) {
4336
delete(m.real, key)
4437
}
4538

4639
// DeleteIf deletes every element if the predicate returns true.
4740
// Returns the amount of elements deleted.
48-
func (m *MutexMap[K, V]) DeleteIf(predicate func(key K, value V) bool) int {
49-
m.Lock()
50-
defer m.Unlock()
51-
41+
func (m *RawMap[K, V]) DeleteIf(predicate func(key K, value V) bool) int {
5242
amount := 0
5343
for key, value := range m.real {
5444
if predicate(key, value) {
@@ -61,31 +51,22 @@ func (m *MutexMap[K, V]) DeleteIf(predicate func(key K, value V) bool) int {
6151
}
6252

6353
// RunAndDelete runs a callback and removes the key afterwards
64-
func (m *MutexMap[K, V]) RunAndDelete(key K, callback func(key K, value V)) {
65-
m.Lock()
66-
defer m.Unlock()
67-
54+
func (m *RawMap[K, V]) RunAndDelete(key K, callback func(key K, value V)) {
6855
if value, ok := m.real[key]; ok {
6956
callback(key, value)
7057
delete(m.real, key)
7158
}
7259
}
7360

7461
// Size returns the length of the internal map
75-
func (m *MutexMap[K, V]) Size() int {
76-
m.RLock()
77-
defer m.RUnlock()
78-
62+
func (m *RawMap[K, V]) Size() int {
7963
return len(m.real)
8064
}
8165

8266
// Each runs a callback function for every item in the map
8367
// The map should not be modified inside the callback function
8468
// Returns true if the loop was terminated early
85-
func (m *MutexMap[K, V]) Each(callback func(key K, value V) bool) bool {
86-
m.RLock()
87-
defer m.RUnlock()
88-
69+
func (m *RawMap[K, V]) Each(callback func(key K, value V) bool) bool {
8970
for key, value := range m.real {
9071
if callback(key, value) {
9172
return true
@@ -95,12 +76,9 @@ func (m *MutexMap[K, V]) Each(callback func(key K, value V) bool) bool {
9576
return false
9677
}
9778

98-
// Clear removes all items from the `real` map
79+
// Clear removes all items from the map
9980
// Accepts an optional callback function ran for every item before it is deleted
100-
func (m *MutexMap[K, V]) Clear(callback func(key K, value V)) {
101-
m.Lock()
102-
defer m.Unlock()
103-
81+
func (m *RawMap[K, V]) Clear(callback func(key K, value V)) {
10482
for key, value := range m.real {
10583
if callback != nil {
10684
callback(key, value)
@@ -109,10 +87,110 @@ func (m *MutexMap[K, V]) Clear(callback func(key K, value V)) {
10987
}
11088
}
11189

90+
// Set sets a key to a given value
91+
func (m *MutexMap[K, V]) Set(key K, value V) {
92+
m.mutex.Lock()
93+
defer m.mutex.Unlock()
94+
95+
m.rawMap.Set(key, value)
96+
}
97+
98+
// Get returns the given key value and a bool if found
99+
func (m *MutexMap[K, V]) Get(key K) (V, bool) {
100+
m.mutex.RLock()
101+
defer m.mutex.RUnlock()
102+
103+
value, ok := m.rawMap.Get(key)
104+
105+
return value, ok
106+
}
107+
108+
// Has checks if a key exists in the map
109+
func (m *MutexMap[K, V]) Has(key K) bool {
110+
m.mutex.RLock()
111+
defer m.mutex.RUnlock()
112+
113+
return m.rawMap.Has(key)
114+
}
115+
116+
// Delete removes a key from the internal map
117+
func (m *MutexMap[K, V]) Delete(key K) {
118+
m.mutex.Lock()
119+
defer m.mutex.Unlock()
120+
121+
m.rawMap.Delete(key)
122+
}
123+
124+
// DeleteIf deletes every element if the predicate returns true.
125+
// Returns the amount of elements deleted.
126+
func (m *MutexMap[K, V]) DeleteIf(predicate func(key K, value V) bool) int {
127+
m.mutex.Lock()
128+
defer m.mutex.Unlock()
129+
130+
return m.rawMap.DeleteIf(predicate)
131+
}
132+
133+
// RunAndDelete runs a callback and removes the key afterwards
134+
func (m *MutexMap[K, V]) RunAndDelete(key K, callback func(key K, value V)) {
135+
m.mutex.Lock()
136+
defer m.mutex.Unlock()
137+
138+
m.rawMap.RunAndDelete(key, callback)
139+
}
140+
141+
// Size returns the length of the internal map
142+
func (m *MutexMap[K, V]) Size() int {
143+
m.mutex.RLock()
144+
defer m.mutex.RUnlock()
145+
146+
return m.rawMap.Size()
147+
}
148+
149+
// Each runs a callback function for every item in the map
150+
// The map should not be modified inside the callback function
151+
// Returns true if the loop was terminated early
152+
func (m *MutexMap[K, V]) Each(callback func(key K, value V) bool) bool {
153+
m.mutex.RLock()
154+
defer m.mutex.RUnlock()
155+
156+
return m.rawMap.Each(callback)
157+
}
158+
159+
// Clear removes all items from the map
160+
// Accepts an optional callback function ran for every item before it is deleted
161+
func (m *MutexMap[K, V]) Clear(callback func(key K, value V)) {
162+
m.mutex.Lock()
163+
defer m.mutex.Unlock()
164+
165+
m.rawMap.Clear(callback)
166+
}
167+
168+
// RMutexSection read-locks the map and runs the provided callback. The map will
169+
// be unlocked after the callback returns. Useful for critical sections where
170+
// multiple map operations are needed. Do not perform write operations to the map.
171+
func (m *MutexMap[K, V]) RMutexSection(callback func(realMap *RawMap[K, V])) {
172+
m.mutex.RLock()
173+
defer m.mutex.RUnlock()
174+
175+
callback(&m.rawMap)
176+
}
177+
178+
// MutexSection write-locks the map and runs the provided callback. The map will
179+
// be unlocked after the callback returns. Useful for critical sections where
180+
// multiple map operations are needed.
181+
func (m *MutexMap[K, V]) MutexSection(callback func(mapInterface *RawMap[K, V])) {
182+
m.mutex.Lock()
183+
defer m.mutex.Unlock()
184+
185+
callback(&m.rawMap)
186+
}
187+
112188
// NewMutexMap returns a new instance of MutexMap with the provided key/value types
113189
func NewMutexMap[K comparable, V any]() *MutexMap[K, V] {
114190
return &MutexMap[K, V]{
115-
RWMutex: &sync.RWMutex{},
116-
real: make(map[K]V),
191+
mutex: &sync.RWMutex{},
192+
rawMap: RawMap[K, V]{
193+
real: make(map[K]V),
194+
},
117195
}
118196
}

0 commit comments

Comments
 (0)