-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathstateful-goroutines.go
109 lines (92 loc) · 2.03 KB
/
stateful-goroutines.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
package main
import (
"fmt"
// "math/rand"
"sync/atomic"
// "time"
)
type readOp struct {
key int
resp chan int
}
type writeOp struct {
key int
val int
resp chan bool
}
func main() {
const nReaders int = 100
const nWriters int = 10
var ops int64 = 0
reads := make(chan *readOp)
writes := make(chan *writeOp)
monitorDone := make(chan bool)
readerDone := make(chan int) // for reader work done notification
writerDone := make(chan int) // for writer work done notification
// as a monitor, receives:
// all read/write requests
// reader/writer work done notification
// sends:
// monitor done after all readers and writers done
go func() {
var state = make(map[int]int) // all data now placed here
var doneReaders int = 0
var doneWriters int = 0
for {
select {
case read := <-reads:
read.resp <- state[read.key] // reply requests value
case write := <-writes:
state[write.key] = write.val
write.resp <- true // reply write success
case /*rid :=*/ <-readerDone:
doneReaders += 1
if doneReaders == nReaders && doneWriters == nWriters {
fmt.Println("state:", state)
monitorDone <- true
break
}
case /*wid :=*/ <-writerDone:
doneWriters += 1
if doneReaders == nReaders && doneWriters == nWriters {
fmt.Println("state:", state)
monitorDone <- true
break
}
}
}
}()
// readers
for r := 0; r < nReaders; r++ {
go func() {
for t := 0; t < 10000; t++ {
read := &readOp {
key: t % 5, // rand.Intn(5)
resp: make(chan int)}
reads <- read
<-read.resp
atomic.AddInt64(&ops, 1)
}
readerDone <- r
}()
}
// writers
for w := 0; w < nWriters; w++ {
go func() {
for t := 0; t < 10000; t++ {
write := &writeOp {
key: t % 5, // rand.Intn(5)
val: t % 100, // rand.Intn(100)
resp: make(chan bool)}
writes <- write
<-write.resp
atomic.AddInt64(&ops, 1)
}
writerDone <- w
}()
}
// wait monitor done
<-monitorDone
opsFinal := atomic.LoadInt64(&ops)
fmt.Println("ops:", opsFinal)
}