@@ -229,6 +229,43 @@ func (m *Map[K, V]) GetOrSet(key K, value V) (actual V, loaded bool) {
229
229
return
230
230
}
231
231
232
+ // CompareAndSwap atomically updates a map entry given its key by comparing current value to `oldValue`
233
+ // and setting it to `newValue` if the above comparison is successful
234
+ // It returns a boolean indicating whether the CompareAndSwap was successful or not
235
+ func (m * Map [K , V ]) CompareAndSwap (key K , oldValue , newValue V ) bool {
236
+ var (
237
+ h = m .hasher (key )
238
+ existing = m .metadata .Load ().indexElement (h )
239
+ )
240
+ if existing == nil || existing .keyHash > h {
241
+ existing = m .listHead
242
+ }
243
+ if _ , current , _ := existing .search (h , key ); current != nil {
244
+ if oldPtr := current .value .Load (); reflect .DeepEqual (* oldPtr , oldValue ) {
245
+ return current .value .CompareAndSwap (oldPtr , & newValue )
246
+ }
247
+ }
248
+ return false
249
+ }
250
+
251
+ // Swap atomically swaps the value of a map entry given its key
252
+ // It returns the old value if swap was successful and a boolean `swapped` indicating whether the swap was successful or not
253
+ func (m * Map [K , V ]) Swap (key K , newValue V ) (oldValue V , swapped bool ) {
254
+ var (
255
+ h = m .hasher (key )
256
+ existing = m .metadata .Load ().indexElement (h )
257
+ )
258
+ if existing == nil || existing .keyHash > h {
259
+ existing = m .listHead
260
+ }
261
+ if _ , current , _ := existing .search (h , key ); current != nil {
262
+ oldValue , swapped = * current .value .Swap (& newValue ), true
263
+ } else {
264
+ swapped = false
265
+ }
266
+ return
267
+ }
268
+
232
269
// ForEach iterates over key-value pairs and executes the lambda provided for each such pair
233
270
// lambda must return `true` to continue iteration and `false` to break iteration
234
271
func (m * Map [K , V ]) ForEach (lambda func (K , V ) bool ) {
0 commit comments