-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontextDemo.go
88 lines (75 loc) · 1.84 KB
/
contextDemo.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
// Run this application.
// Try to change behavior and look what it will give you.
// Also you may catch deadlock in this application. Try to fix it by your own.
// Valid code without bug is in presentation.
package main
import (
"context"
"fmt"
"math/rand"
"sync"
"time"
)
var GlobalResource chan int
func main() {
ctx, cancel := context.WithCancel(context.Background())
wg := &sync.WaitGroup{}
GlobalResource = NewResource(ctx, wg)
wg.Add(1)
go Worker(ctx, wg)
time.Sleep(time.Second * 2)
cancel()
wg.Wait()
fmt.Println("Main goroutine stoping")
}
func Worker(ctx context.Context, wg *sync.WaitGroup) {
defer func() {
fmt.Println("Worker was stoped")
wg.Done()
}()
fmt.Println("Worker was started")
childWG := &sync.WaitGroup{}
for i := 0; i < 3; i++ {
childWG.Add(1)
go SubWorker(ctx, childWG, i)
}
// Will wait until main would not call cancel()
<-ctx.Done()
fmt.Println("Worker receiver ctx.Done signal. Waiting for SubWorkers")
childWG.Wait()
}
func SubWorker(ctx context.Context, wg *sync.WaitGroup, index int) {
defer func() {
fmt.Printf("SubWorker %d was stoped\n", index)
wg.Done()
}()
fmt.Printf("SubWorker #%d was started\n", index)
for {
select {
case <-ctx.Done():
sleepTime := rand.Intn(200)
fmt.Printf("SubWorker #%d Received ctx.Done signal. Stoping in %d Milliseconds\n", index, sleepTime)
time.Sleep(time.Millisecond * time.Duration(sleepTime))
return
case <-time.After(time.Second):
random := <-GlobalResource
fmt.Printf("Tick from SubWorker #%d with value %d\n", index, random)
}
}
}
func NewResource(ctx context.Context, wg *sync.WaitGroup) chan int {
out := make(chan int)
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case <-ctx.Done():
fmt.Println("Resource received ctx.Done signal")
return
case out <- rand.Intn(200):
}
}
}()
return out
}