]> Cypherpunks.ru repositories - gostls13.git/commitdiff
sync: document why copyChecker checks the condition twice
authorqiulaidongfeng <2645477756@qq.com>
Tue, 15 Aug 2023 02:14:00 +0000 (02:14 +0000)
committerGopher Robot <gobot@golang.org>
Wed, 16 Aug 2023 15:36:31 +0000 (15:36 +0000)
Fixes #40924

Change-Id: I249a278be1ec3c67088819af4456e6c393431724

Change-Id: I249a278be1ec3c67088819af4456e6c393431724
GitHub-Last-Rev: 772c7ae7e140ebd3896fc7786aae8b43ab3128c3
GitHub-Pull-Request: golang/go#61978
Reviewed-on: https://go-review.googlesource.com/c/go/+/518961
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Austin Clements <austin@google.com>
Auto-Submit: Austin Clements <austin@google.com>

src/sync/cond.go

index cc927adf584f02206cc46d198b706021706bc6fb..7ef3188a1ee84d35f4633a4fa3038572211f9c13 100644 (file)
@@ -96,6 +96,10 @@ func (c *Cond) Broadcast() {
 type copyChecker uintptr
 
 func (c *copyChecker) check() {
+       // Check if c has been copied in three steps:
+       // 1. The first comparison is the fast-path. If c has been initialized and not copied, this will return immediately. Otherwise, c is either not initialized, or has been copied.
+       // 2. Ensure c is initialized. If the CAS succeeds, we're done. If it fails, c was either initialized concurrently and we simply lost the race, or c has been copied.
+       // 3. Do step 1 again. Now that c is definitely initialized, if this fails, c was copied.
        if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&
                !atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) &&
                uintptr(*c) != uintptr(unsafe.Pointer(c)) {