mirror of
https://github.com/golang/go
synced 2024-11-22 01:04:40 -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:
parent
81592c298b
commit
93dde6b0e6
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user