blob: 157a3667a64e396c8d78df9954d29d70f39ead7f [file] [log] [blame]
Rob Pike895c5db2010-08-05 13:31:10 +10001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package sync_test
6
7import (
8 . "sync"
Dmitriy Vyukov3a4a5812011-06-27 16:02:13 -04009 "sync/atomic"
10 "runtime"
Rob Pike895c5db2010-08-05 13:31:10 +100011 "testing"
12)
13
14type one int
15
16func (o *one) Increment() {
17 *o++
18}
19
20func run(once *Once, o *one, c chan bool) {
21 once.Do(func() { o.Increment() })
22 c <- true
23}
24
25func TestOnce(t *testing.T) {
26 o := new(one)
27 once := new(Once)
28 c := make(chan bool)
29 const N = 10
30 for i := 0; i < N; i++ {
31 go run(once, o, c)
32 }
33 for i := 0; i < N; i++ {
34 <-c
35 }
36 if *o != 1 {
37 t.Errorf("once failed: %d is not 1", *o)
38 }
39}
Dmitriy Vyukov3a4a5812011-06-27 16:02:13 -040040
41func BenchmarkOnce(b *testing.B) {
42 const CallsPerSched = 1000
43 procs := runtime.GOMAXPROCS(-1)
44 N := int32(b.N / CallsPerSched)
45 var once Once
46 f := func() {}
47 c := make(chan bool, procs)
48 for p := 0; p < procs; p++ {
49 go func() {
50 for atomic.AddInt32(&N, -1) >= 0 {
51 runtime.Gosched()
52 for g := 0; g < CallsPerSched; g++ {
53 once.Do(f)
54 }
55 }
56 c <- true
57 }()
58 }
59 for p := 0; p < procs; p++ {
60 <-c
61 }
62}