1
0
mirror of https://github.com/golang/go synced 2024-11-21 18:34:44 -07:00

sync: add fast path to Once

The implementation does not grab the lock,
if Once is already initalized.
Benchmark results on HP Z600 (2 x Xeon E5620, 8 HT cores, 2.40GHz)
are as follows:
benchmark                                        old ns/op    new ns/op    delta
sync_test.BenchmarkOnce                             187.00        14.00  -92.51%
sync_test.BenchmarkOnce-2                           909.00        21.40  -97.65%
sync_test.BenchmarkOnce-4                          3684.00        20.90  -99.43%
sync_test.BenchmarkOnce-8                          5987.00        23.00  -99.62%
sync_test.BenchmarkOnce-16                         5051.00        21.60  -99.57%

R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/4641066
This commit is contained in:
Dmitriy Vyukov 2011-06-28 09:43:01 -04:00 committed by Russ Cox
parent 81592c298b
commit 93dde6b0e6

View File

@ -4,10 +4,14 @@
package sync
import (
"sync/atomic"
)
// Once is an object that will perform exactly one action.
type Once struct {
m Mutex
done bool
done int32
}
// Do calls the function f if and only if the method is being called for the
@ -26,10 +30,14 @@ type Once struct {
// Do to be called, it will deadlock.
//
func (o *Once) Do(f func()) {
if atomic.AddInt32(&o.done, 0) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if !o.done {
o.done = true
if o.done == 0 {
f()
atomic.CompareAndSwapInt32(&o.done, 0, 1)
}
}