mirror of
https://github.com/golang/go
synced 2024-11-22 00:54:43 -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
|
package sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
// Once is an object that will perform exactly one action.
|
// Once is an object that will perform exactly one action.
|
||||||
type Once struct {
|
type Once struct {
|
||||||
m Mutex
|
m Mutex
|
||||||
done bool
|
done int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do calls the function f if and only if the method is being called for the
|
// 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.
|
// Do to be called, it will deadlock.
|
||||||
//
|
//
|
||||||
func (o *Once) Do(f func()) {
|
func (o *Once) Do(f func()) {
|
||||||
|
if atomic.AddInt32(&o.done, 0) == 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Slow-path.
|
||||||
o.m.Lock()
|
o.m.Lock()
|
||||||
defer o.m.Unlock()
|
defer o.m.Unlock()
|
||||||
if !o.done {
|
if o.done == 0 {
|
||||||
o.done = true
|
|
||||||
f()
|
f()
|
||||||
|
atomic.CompareAndSwapInt32(&o.done, 0, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user