github.com/djordje200179/extendedlibrary/datastructures@v1.7.1-0.20240227175559-d09520a92dd4/maps/syncmap/wrapper.go (about) 1 package syncmap 2 3 import ( 4 "github.com/djordje200179/extendedlibrary/datastructures/iter" 5 "github.com/djordje200179/extendedlibrary/datastructures/maps" 6 "github.com/djordje200179/extendedlibrary/misc" 7 "sync" 8 ) 9 10 // Wrapper is a wrapper around a map that provides thread-safe access to the map. 11 // Locking is done through read-write mutex. This means that multiple goroutines can read from the map at the same time, 12 // but only one goroutine can write to the map at the same time. 13 type Wrapper[K, V any] struct { 14 m maps.Map[K, V] 15 16 mutex sync.RWMutex 17 } 18 19 // From creates a new Wrapper from the given map. 20 func From[K, V any](m maps.Map[K, V]) *Wrapper[K, V] { 21 return &Wrapper[K, V]{m, sync.RWMutex{}} 22 } 23 24 // Size returns the number of entries in the map. 25 func (w *Wrapper[K, V]) Size() int { 26 w.mutex.RLock() 27 defer w.mutex.RUnlock() 28 29 return w.m.Size() 30 } 31 32 // Contains returns true if the map contains the given key. 33 func (w *Wrapper[K, V]) Contains(key K) bool { 34 w.mutex.RLock() 35 defer w.mutex.RUnlock() 36 37 return w.m.Contains(key) 38 } 39 40 // TryGet returns the value associated with the given key, and true if the key exists. 41 // If the key does not exist, the default value for the value type is returned, and false is returned. 42 func (w *Wrapper[K, V]) TryGet(key K) (V, bool) { 43 w.mutex.RLock() 44 defer w.mutex.RUnlock() 45 46 return w.m.TryGet(key) 47 } 48 49 // Get returns the value associated with the given key. 50 func (w *Wrapper[K, V]) Get(key K) V { 51 w.mutex.RLock() 52 defer w.mutex.RUnlock() 53 54 return w.m.Get(key) 55 } 56 57 // GetRef returns a reference to the value associated with the given key. 58 // Usage of this method is discouraged, as it breaks the thread-safety of the map. 59 // Lock will not be held while the reference is used, so it is possible that the value of the element changes while the reference is used. 60 func (w *Wrapper[K, V]) GetRef(key K) *V { 61 w.mutex.RLock() 62 defer w.mutex.RUnlock() 63 64 return w.m.GetRef(key) 65 } 66 67 // Set sets the value associated with the given key. 68 func (w *Wrapper[K, V]) Set(key K, value V) { 69 w.mutex.Lock() 70 defer w.mutex.Unlock() 71 72 w.m.Set(key, value) 73 } 74 75 // Update updates the value associated with the given key. 76 func (w *Wrapper[K, V]) Update(key K, updateFunction func(oldValue V) V) { 77 w.mutex.Lock() 78 defer w.mutex.Unlock() 79 80 oldValue := w.m.Get(key) 81 newValue := updateFunction(oldValue) 82 83 w.m.Set(key, newValue) 84 } 85 86 // UpdateRef updates the value associated with the given key. 87 func (w *Wrapper[K, V]) UpdateRef(key K, updateFunction func(oldValue *V)) { 88 w.mutex.Lock() 89 defer w.mutex.Unlock() 90 91 oldValue := w.m.GetRef(key) 92 updateFunction(oldValue) 93 } 94 95 // Remove removes the entry with the given key. 96 func (w *Wrapper[K, V]) Remove(key K) { 97 w.mutex.Lock() 98 defer w.mutex.Unlock() 99 100 w.m.Remove(key) 101 } 102 103 // Clear removes all entries from the map. 104 func (w *Wrapper[K, V]) Clear() { 105 w.mutex.Lock() 106 defer w.mutex.Unlock() 107 108 w.m.Clear() 109 } 110 111 // Clone returns a copy of the wrapper and the underlying map. 112 func (w *Wrapper[K, V]) Clone() maps.Map[K, V] { 113 w.mutex.RLock() 114 defer w.mutex.RUnlock() 115 116 clonedMap := w.m.Clone() 117 return &Wrapper[K, V]{clonedMap, sync.RWMutex{}} 118 } 119 120 // Iterator returns an iter.Iterator over the map. 121 func (w *Wrapper[K, V]) Iterator() iter.Iterator[misc.Pair[K, V]] { 122 return w.MapIterator() 123 } 124 125 // MapIterator returns an iterator over the map. 126 func (w *Wrapper[K, V]) MapIterator() maps.Iterator[K, V] { 127 return Iterator[K, V]{w.m.MapIterator(), &w.mutex} 128 } 129 130 // Stream2 streams over the entries in the Map. 131 func (w *Wrapper[K, V]) Stream2(yield func(K, V) bool) { 132 w.mutex.RLock() 133 defer w.mutex.RUnlock() 134 135 w.m.Stream2(yield) 136 } 137 138 // RefsStream2 streams over the keys and references to the values in the Map. 139 func (w *Wrapper[K, V]) RefsStream2(yield func(K, *V) bool) { 140 w.mutex.Lock() 141 defer w.mutex.Unlock() 142 143 w.m.RefsStream2(yield) 144 } 145 146 // Transaction executes the given function with the map as an argument. 147 // The map is locked for writing while the function is executed. 148 func (w *Wrapper[K, V]) Transaction(updateFunction func(m maps.Map[K, V])) { 149 w.mutex.Lock() 150 defer w.mutex.Unlock() 151 152 updateFunction(w.m) 153 }