]> Cypherpunks.ru repositories - gostls13.git/commitdiff
sync: convert Once.done to atomic type
authorcuiweixie <cuiweixie@gmail.com>
Fri, 2 Sep 2022 03:06:58 +0000 (11:06 +0800)
committerGopher Robot <gobot@golang.org>
Tue, 6 Sep 2022 16:53:51 +0000 (16:53 +0000)
Change-Id: I49f8c764d49cabaad4d6859c219ba7220a389c1f
Reviewed-on: https://go-review.googlesource.com/c/go/+/427140
Run-TryBot: xie cui <523516579@qq.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/sync/once.go
test/inline_sync.go

index b6399cfc3d100a657f545000cf651e4a95ccd737..587eab0af9d471ece45d5633d726995fec6d7fa7 100644 (file)
@@ -16,13 +16,13 @@ import (
 // the return from f “synchronizes before”
 // the return from any call of once.Do(f).
 type Once struct {
+       m Mutex
        // done indicates whether the action has been performed.
        // It is first in the struct because it is used in the hot path.
        // The hot path is inlined at every call site.
        // Placing done first allows more compact instructions on some architectures (amd64/386),
        // and fewer instructions (to calculate offset) on other architectures.
-       done uint32
-       m    Mutex
+       done atomic.Bool
 }
 
 // Do calls the function f if and only if Do is being called for the
@@ -48,7 +48,7 @@ type Once struct {
 func (o *Once) Do(f func()) {
        // Note: Here is an incorrect implementation of Do:
        //
-       //      if atomic.CompareAndSwapUint32(&o.done, 0, 1) {
+       //      if o.done.CompareAndSwap(false, true) {
        //              f()
        //      }
        //
@@ -58,9 +58,9 @@ func (o *Once) Do(f func()) {
        // call f, and the second would return immediately, without
        // waiting for the first's call to f to complete.
        // This is why the slow path falls back to a mutex, and why
-       // the atomic.StoreUint32 must be delayed until after f returns.
+       // the o.done.Store must be delayed until after f returns.
 
-       if atomic.LoadUint32(&o.done) == 0 {
+       if !o.done.Load() {
                // Outlined slow-path to allow inlining of the fast-path.
                o.doSlow(f)
        }
@@ -69,8 +69,8 @@ func (o *Once) Do(f func()) {
 func (o *Once) doSlow(f func()) {
        o.m.Lock()
        defer o.m.Unlock()
-       if o.done == 0 {
-               defer atomic.StoreUint32(&o.done, 1)
+       if !o.done.Load() {
+               defer o.done.Store(true)
                f()
        }
 }
index 30b436af41289cb4b016bc34b401dd9e1a9880a2..d1ce5f521cf0bb7e8733bb12050cf5d38efa69a2 100644 (file)
@@ -36,7 +36,7 @@ var once *sync.Once
 
 func small7() { // ERROR "can inline small7"
         // the Do fast path should be inlined
-        once.Do(small5) // ERROR "inlining call to sync\.\(\*Once\)\.Do"
+        once.Do(small5) // ERROR "(inlining call to sync\.\(\*Once\)\.Do|inlining call to atomic\.\(\*Bool\)\.Load)"
 }
 
 var rwmutex *sync.RWMutex