-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtestBarberProblem.go
174 lines (159 loc) · 4.02 KB
/
testBarberProblem.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package main
import (
"fmt"
"sync"
"time"
)
const (
sleeping = iota
checking
cutting
)
var stateLog = map[int]string{
0: "Sleeping",
1: "Checking",
2: "Cutting",
}
var wg *sync.WaitGroup // Amount of potentional customers
type Barber struct {
name string
sync.Mutex
state int // Sleeping/Checking/Cutting
customer *Customer
}
type Customer struct {
name string
}
func (c *Customer) String() string {
return fmt.Sprintf("%p", c)[7:]
}
func NewBarber() (b *Barber) {
return &Barber{
name: "Sam",
state: sleeping,
}
}
// Barber goroutine
// Checks for customers
// Sleeps - wait for wakers to wake him up
func barber(b *Barber, wr chan *Customer, wakers chan *Customer) {
for {
b.Lock()
defer b.Unlock()
b.state = checking
b.customer = nil
// checking the waiting room
fmt.Printf("Checking waiting room: %d\n", len(wr))
time.Sleep(time.Millisecond * 100)
select {
case c := <-wr:
HairCut(c, b)
b.Unlock()
default: // Waiting room is empty
fmt.Printf("Sleeping Barber - %s\n", b.customer)
b.state = sleeping
b.customer = nil
b.Unlock()
c := <-wakers
b.Lock()
fmt.Printf("Woken by %s\n", c)
HairCut(c, b)
b.Unlock()
}
}
}
func HairCut(c *Customer, b *Barber) {
b.state = cutting
b.customer = c
b.Unlock()
fmt.Printf("Cutting %s hair\n", c)
time.Sleep(time.Millisecond * 100)
b.Lock()
wg.Done()
b.customer = nil
}
// customer goroutine
// just fizzles out if it's full, otherwise the customer
// is passed along to the channel handling it's haircut etc
func customer(c *Customer, b *Barber, wr chan<- *Customer, wakers chan<- *Customer) {
// arrive
time.Sleep(time.Millisecond * 50)
// Check on barber
b.Lock()
fmt.Printf("Customer %s checks %s barber | room: %d, w %d - customer: %s\n",
c, stateLog[b.state], len(wr), len(wakers), b.customer)
switch b.state {
case sleeping:
select {
case wakers <- c:
// below lines are not mandatory
// default:
// select {
// case wr <- c:
// default:
// wg.Done()
// }
}
case cutting:
select {
case wr <- c:
default: // Full waiting room, leave shop
wg.Done()
}
// below lines are not mandatory
// case checking:
// panic("Customer shouldn't check for the Barber when Barber is Checking the waiting room")
}
b.Unlock()
}
func main() {
b := NewBarber()
b.name = "Rocky"
WaitingRoom := make(chan *Customer, 5) // 5 chairs
Wakers := make(chan *Customer, 1) // Only one waker at a time
go barber(b, WaitingRoom, Wakers)
time.Sleep(time.Millisecond * 100)
wg = new(sync.WaitGroup)
n := 10
wg.Add(10)
// Spawn customers
for i := 0; i < n; i++ {
time.Sleep(time.Millisecond * 50)
c := new(Customer)
go customer(c, b, WaitingRoom, Wakers)
}
wg.Wait()
fmt.Println("No more customers for the day")
}
// Checking waiting room: 0
// Sleeping Barber - <nil>
// Customer 48250 checks Sleeping barber | room: 0, w 0 - customer: <nil>
// Woken by 48250
// Cutting 48250 hair
// Customer 48260 checks Cutting barber | room: 0, w 0 - customer: 48250
// Checking waiting room: 1
// Cutting 48260 hair
// Customer 1e000 checks Cutting barber | room: 0, w 0 - customer: 48260
// Customer 86020 checks Cutting barber | room: 1, w 0 - customer: 48260
// Customer 1e020 checks Cutting barber | room: 2, w 0 - customer: 48260
// Customer 48280 checks Cutting barber | room: 3, w 0 - customer: 48260
// Checking waiting room: 4
// Cutting 1e000 hair
// Customer 86070 checks Cutting barber | room: 3, w 0 - customer: 1e000
// Customer 1e030 checks Cutting barber | room: 4, w 0 - customer: 1e000
// Customer 1e040 checks Cutting barber | room: 5, w 0 - customer: 1e000
// Checking waiting room: 5
// Cutting 86020 hair
// Customer 1e050 checks Cutting barber | room: 4, w 0 - customer: 86020
// Checking waiting room: 5
// Cutting 1e020 hair
// Checking waiting room: 4
// Cutting 48280 hair
// Checking waiting room: 3
// Cutting 86070 hair
// Checking waiting room: 2
// Cutting 1e030 hair
// Checking waiting room: 1
// Cutting 1e050 hair
// Checking waiting room: 0
// No more customers for the day