@@ -244,18 +244,24 @@ func (m *Map[K, V]) Store(key K, value V) {
244244 return value , UpdateOp
245245 },
246246 false ,
247+ 0 ,
247248 )
248249}
249250
250251// LoadOrStore returns the existing value for the key if present.
251252// Otherwise, it stores and returns the given value.
252253// The loaded result is true if the value was loaded, false if stored.
253254func (m * Map [K , V ]) LoadOrStore (key K , value V ) (actual V , loaded bool ) {
254- return m .doLoadOrCompute (
255+ return m .doCompute (
255256 key ,
256- func (V , bool ) (V , ComputeOp ) {
257+ func (oldValue V , loaded bool ) (V , ComputeOp ) {
258+ if loaded {
259+ return oldValue , CancelOp
260+ }
257261 return value , UpdateOp
258262 },
263+ false ,
264+ 1 ,
259265 )
260266}
261267
@@ -271,6 +277,7 @@ func (m *Map[K, V]) LoadAndStore(key K, value V) (actual V, loaded bool) {
271277 return value , UpdateOp
272278 },
273279 false ,
280+ 0 ,
274281 )
275282}
276283
@@ -290,7 +297,7 @@ func (m *Map[K, V]) LoadOrCompute(
290297 key K ,
291298 valueFn func () (newValue V , cancel bool ),
292299) (value V , loaded bool ) {
293- return m .doLoadOrCompute (
300+ return m .doCompute (
294301 key ,
295302 func (oldValue V , loaded bool ) (V , ComputeOp ) {
296303 if loaded {
@@ -302,6 +309,8 @@ func (m *Map[K, V]) LoadOrCompute(
302309 }
303310 return oldValue , CancelOp
304311 },
312+ false ,
313+ 1 ,
305314 )
306315}
307316
@@ -345,7 +354,7 @@ func (m *Map[K, V]) Compute(
345354 key K ,
346355 valueFn func (oldValue V , loaded bool ) (newValue V , op ComputeOp ),
347356) (actual V , ok bool ) {
348- return m .doCompute (key , valueFn , true )
357+ return m .doCompute (key , valueFn , true , 0 )
349358}
350359
351360// LoadAndDelete deletes the value for a key, returning the previous
@@ -358,6 +367,7 @@ func (m *Map[K, V]) LoadAndDelete(key K) (value V, loaded bool) {
358367 return value , DeleteOp
359368 },
360369 false ,
370+ - 1 ,
361371 )
362372}
363373
@@ -369,14 +379,17 @@ func (m *Map[K, V]) Delete(key K) {
369379 return value , DeleteOp
370380 },
371381 false ,
382+ - 1 ,
372383 )
373384}
374385
375386func (m * Map [K , V ]) doCompute (
376387 key K ,
377388 valueFn func (oldValue V , loaded bool ) (V , ComputeOp ),
378389 computeOnly bool ,
390+ loadExitFlag int8 ,
379391) (V , bool ) {
392+
380393 for {
381394 compute_attempt:
382395 var (
@@ -391,6 +404,36 @@ func (m *Map[K, V]) doCompute(
391404 h2w := broadcast (h2 )
392405 bidx := uint64 (len (table .buckets )- 1 ) & h1
393406 rootb := & table .buckets [bidx ]
407+
408+ if loadExitFlag != 0 {
409+ b := rootb
410+ load:
411+ for {
412+ metaw := b .meta .Load ()
413+ markedw := markZeroBytes (metaw ^ h2w ) & metaMask
414+ for markedw != 0 {
415+ idx := firstMarkedByteIndex (markedw )
416+ e := b .entries [idx ].Load ()
417+ if e != nil {
418+ if e .key == key {
419+ if loadExitFlag == 1 {
420+ return e .value , true
421+ }
422+ break load
423+ }
424+ }
425+ markedw &= markedw - 1
426+ }
427+ b = b .next .Load ()
428+ if b == nil {
429+ if loadExitFlag == - 1 {
430+ return * new (V ), false
431+ }
432+ break load
433+ }
434+ }
435+ }
436+
394437 rootb .mu .Lock ()
395438 // The following two checks must go in reverse to what's
396439 // in the resize method.
@@ -517,121 +560,6 @@ func (m *Map[K, V]) doCompute(
517560 }
518561}
519562
520- func (m * Map [K , V ]) doLoadOrCompute (
521- key K ,
522- valueFn func (oldValue V , loaded bool ) (V , ComputeOp ),
523- ) (V , bool ) {
524- // Read-only path.
525- if v , ok := m .Load (key ); ok {
526- return v , true
527- }
528- // Write path.
529- for {
530- compute_attempt:
531- var (
532- emptyb * bucketPadded [K , V ]
533- emptyidx int
534- )
535- table := m .table .Load ()
536- tableLen := len (table .buckets )
537- hash := maphash .Comparable (table .seed , key )
538- h1 := h1 (hash )
539- h2 := h2 (hash )
540- h2w := broadcast (h2 )
541- bidx := uint64 (len (table .buckets )- 1 ) & h1
542- rootb := & table .buckets [bidx ]
543- rootb .mu .Lock ()
544- // The following two checks must go in reverse to what's
545- // in the resize method.
546- if m .resizeInProgress () {
547- // Resize is in progress. Wait, then go for another attempt.
548- rootb .mu .Unlock ()
549- m .waitForResize ()
550- goto compute_attempt
551- }
552- if m .newerTableExists (table ) {
553- // Someone resized the table. Go for another attempt.
554- rootb .mu .Unlock ()
555- goto compute_attempt
556- }
557- b := rootb
558- for {
559- metaw := b .meta .Load ()
560- markedw := markZeroBytes (metaw ^ h2w ) & metaMask
561- for markedw != 0 {
562- idx := firstMarkedByteIndex (markedw )
563- e := b .entries [idx ].Load ()
564- if e != nil {
565- if e .key == key {
566- rootb .mu .Unlock ()
567- return e .value , true
568- }
569- }
570- markedw &= markedw - 1
571- }
572- if emptyb == nil {
573- // Search for empty entries (up to 5 per bucket).
574- emptyw := metaw & defaultMetaMasked
575- if emptyw != 0 {
576- idx := firstMarkedByteIndex (emptyw )
577- emptyb = b
578- emptyidx = idx
579- }
580- }
581- if b .next .Load () == nil {
582- if emptyb != nil {
583- // Insertion into an existing bucket.
584- var zeroV V
585- newValue , op := valueFn (zeroV , false )
586- switch op {
587- case DeleteOp , CancelOp :
588- rootb .mu .Unlock ()
589- return zeroV , false
590- default :
591- newe := new (entry [K , V ])
592- newe .key = key
593- newe .value = newValue
594- // First we update meta, then the entry.
595- emptyb .meta .Store (setByte (emptyb .meta .Load (), h2 , emptyidx ))
596- emptyb .entries [emptyidx ].Store (newe )
597- rootb .mu .Unlock ()
598- table .addSize (bidx , 1 )
599- return newValue , false
600- }
601- }
602- growThreshold := float64 (tableLen ) * entriesPerMapBucket * mapLoadFactor
603- if table .sumSize () > int64 (growThreshold ) {
604- // Need to grow the table. Then go for another attempt.
605- rootb .mu .Unlock ()
606- m .resize (table , mapGrowHint )
607- goto compute_attempt
608- }
609- // Insertion into a new bucket.
610- var zeroV V
611- newValue , op := valueFn (zeroV , false )
612- switch op {
613- case DeleteOp , CancelOp :
614- rootb .mu .Unlock ()
615- return newValue , false
616- default :
617- // Create and append a bucket.
618- newb := new (bucketPadded [K , V ])
619- newb .meta .Store (setByte (defaultMeta , h2 , 0 ))
620- newe := new (entry [K , V ])
621- newe .key = key
622- newe .value = newValue
623- newb .entries [0 ].Store (newe )
624- b .next .Store (newb )
625- rootb .mu .Unlock ()
626- table .addSize (bidx , 1 )
627- return newValue , false
628- }
629- }
630- b = b .next .Load ()
631- }
632- }
633- }
634-
635563func (m * Map [K , V ]) newerTableExists (table * mapTable [K , V ]) bool {
636564 return table != m .table .Load ()
637565}
0 commit comments