| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package synctest provides support for testing concurrent code. |
| // |
| // See the testing/synctest package for function documentation. |
| package synctest |
| |
| import ( |
| _ "unsafe" // for go:linkname |
| ) |
| |
| //go:linkname Run |
| func Run(f func()) |
| |
| //go:linkname Wait |
| func Wait() |
| |
| //go:linkname acquire |
| func acquire() any |
| |
| //go:linkname release |
| func release(any) |
| |
| //go:linkname inBubble |
| func inBubble(any, func()) |
| |
| // A Bubble is a synctest bubble. |
| // |
| // Not a public API. Used by syscall/js to propagate bubble membership through syscalls. |
| type Bubble struct { |
| b any |
| } |
| |
| // Acquire returns a reference to the current goroutine's bubble. |
| // The bubble will not become idle until Release is called. |
| func Acquire() *Bubble { |
| if b := acquire(); b != nil { |
| return &Bubble{b} |
| } |
| return nil |
| } |
| |
| // Release releases the reference to the bubble, |
| // allowing it to become idle again. |
| func (b *Bubble) Release() { |
| if b == nil { |
| return |
| } |
| release(b.b) |
| b.b = nil |
| } |
| |
| // Run executes f in the bubble. |
| // The current goroutine must not be part of a bubble. |
| func (b *Bubble) Run(f func()) { |
| if b == nil { |
| f() |
| } else { |
| inBubble(b.b, f) |
| } |
| } |