-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcondition_variables_test.go
84 lines (72 loc) · 1.24 KB
/
condition_variables_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package main
import (
"fmt"
"math/rand"
"runtime"
"sync"
"testing"
)
// Condition variable page 37
type ItemCondition = int
type Queue struct {
mu sync.Mutex
items []ItemCondition
itemAdded sync.Cond
}
func NewQueue() *Queue {
q := new(Queue)
q.itemAdded.L = &q.mu
return q
}
func (q *Queue) Get() ItemCondition {
q.mu.Lock()
defer q.mu.Unlock()
for len(q.items) == 0 {
q.itemAdded.Wait()
}
ItemCondition := q.items[0]
q.items = q.items[1:]
return ItemCondition
}
func (q *Queue) Put(item ItemCondition) {
q.mu.Lock()
defer q.mu.Unlock()
q.items = append(q.items, item)
q.itemAdded.Signal()
}
func (q *Queue) GetMany(n int) []ItemCondition {
q.mu.Lock()
defer q.mu.Unlock()
for len(q.items) < n {
q.itemAdded.Wait()
}
items := q.items[:n:n]
q.items = q.items[n:]
return items
}
func randYield() {
if rand.Intn(3) == 0 {
runtime.Gosched()
}
}
func TestWaitAndSignal(t *testing.T) {
/*
go test -run=TestConditionalVariable -v
*/
q := NewQueue()
var wg sync.WaitGroup
for n := 10; n > 0; n-- {
wg.Add(1)
go func(n int) {
randYield()
items := q.GetMany(n)
fmt.Printf("%2d: %2d\n", n, items)
wg.Done()
}(n)
}
for i := 0; i < 100; i++ {
q.Put(i)
runtime.Gosched()
}
wg.Wait()
}