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  }