libgo: Merge from revision 18783:00cce3a34d7e of master library.
[official-gcc.git] / libgo / go / sync / pool_test.go
blobf88dab494367dc236cf0568de334f0d051af9ff1
1 // Copyright 2013 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.
5 package sync_test
7 import (
8 "runtime"
9 "runtime/debug"
10 . "sync"
11 "sync/atomic"
12 "testing"
13 "time"
14 "unsafe"
17 func TestPool(t *testing.T) {
18 // disable GC so we can control when it happens.
19 defer debug.SetGCPercent(debug.SetGCPercent(-1))
20 var p Pool
21 if p.Get() != nil {
22 t.Fatal("expected empty")
24 p.Put("a")
25 p.Put("b")
26 if g := p.Get(); g != "b" {
27 t.Fatalf("got %#v; want b", g)
29 if g := p.Get(); g != "a" {
30 t.Fatalf("got %#v; want a", g)
32 if g := p.Get(); g != nil {
33 t.Fatalf("got %#v; want nil", g)
36 p.Put("c")
37 debug.SetGCPercent(100) // to allow following GC to actually run
38 runtime.GC()
39 if g := p.Get(); g != nil {
40 t.Fatalf("got %#v; want nil after GC", g)
44 func TestPoolNew(t *testing.T) {
45 // disable GC so we can control when it happens.
46 defer debug.SetGCPercent(debug.SetGCPercent(-1))
48 i := 0
49 p := Pool{
50 New: func() interface{} {
51 i++
52 return i
55 if v := p.Get(); v != 1 {
56 t.Fatalf("got %v; want 1", v)
58 if v := p.Get(); v != 2 {
59 t.Fatalf("got %v; want 2", v)
61 p.Put(42)
62 if v := p.Get(); v != 42 {
63 t.Fatalf("got %v; want 42", v)
65 if v := p.Get(); v != 3 {
66 t.Fatalf("got %v; want 3", v)
70 // Test that Pool does not hold pointers to previously cached
71 // resources
72 func TestPoolGC(t *testing.T) {
73 var p Pool
74 var fin uint32
75 const N = 100
76 for i := 0; i < N; i++ {
77 v := new(int)
78 runtime.SetFinalizer(v, func(vv *int) {
79 atomic.AddUint32(&fin, 1)
81 p.Put(v)
83 for i := 0; i < N; i++ {
84 p.Get()
86 for i := 0; i < 5; i++ {
87 runtime.GC()
88 time.Sleep(time.Millisecond)
89 // 1 pointer can remain on stack or elsewhere
90 if atomic.LoadUint32(&fin) >= N-1 {
91 return
94 // gccgo has a less precise heap.
95 if runtime.Compiler == "gccgo" && atomic.LoadUint32(&fin) >= N-5 {
96 return
99 t.Fatalf("only %v out of %v resources are finalized",
100 atomic.LoadUint32(&fin), N)
103 func TestPoolStress(t *testing.T) {
104 const P = 10
105 N := int(1e6)
106 if testing.Short() {
107 N /= 100
109 var p Pool
110 done := make(chan bool)
111 for i := 0; i < P; i++ {
112 go func() {
113 var v interface{} = 0
114 for j := 0; j < N; j++ {
115 if v == nil {
116 v = 0
118 p.Put(v)
119 v = p.Get()
120 if v != nil && v.(int) != 0 {
121 t.Fatalf("expect 0, got %v", v)
124 done <- true
127 for i := 0; i < P; i++ {
128 <-done
132 func BenchmarkPool(b *testing.B) {
133 procs := runtime.GOMAXPROCS(-1)
134 var dec func() bool
135 if unsafe.Sizeof(b.N) == 8 {
136 n := int64(b.N)
137 dec = func() bool {
138 return atomic.AddInt64(&n, -1) >= 0
140 } else {
141 n := int32(b.N)
142 dec = func() bool {
143 return atomic.AddInt32(&n, -1) >= 0
146 var p Pool
147 var wg WaitGroup
148 for i := 0; i < procs; i++ {
149 wg.Add(1)
150 go func() {
151 defer wg.Done()
152 for dec() {
153 p.Put(1)
154 p.Get()
158 wg.Wait()