aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/sync/once.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/sync/once.go')
-rw-r--r--libgo/go/sync/once.go16
1 files changed, 12 insertions, 4 deletions
diff --git a/libgo/go/sync/once.go b/libgo/go/sync/once.go
index d8ef952..8476197 100644
--- a/libgo/go/sync/once.go
+++ b/libgo/go/sync/once.go
@@ -10,8 +10,13 @@ import (
// Once is an object that will perform exactly one action.
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/x86),
+ // and fewer instructions (to calculate offset) on other architectures.
done uint32
+ m Mutex
}
// Do calls the function f if and only if Do is being called for the
@@ -33,10 +38,13 @@ type Once struct {
// without calling f.
//
func (o *Once) Do(f func()) {
- if atomic.LoadUint32(&o.done) == 1 {
- return
+ if atomic.LoadUint32(&o.done) == 0 {
+ // Outlined slow-path to allow inlining of the fast-path.
+ o.doSlow(f)
}
- // Slow-path.
+}
+
+func (o *Once) doSlow(f func()) {
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {