1
2
3
4
5
12 package main
13
14 import (
15 "math/rand"
16 "os"
17 "runtime/pprof"
18 "sync"
19 "time"
20 )
21
22 func init() {
23 register("Moby21233", Moby21233)
24 }
25
26 type Progress_moby21233 struct{}
27
28 type Output_moby21233 interface {
29 WriteProgress(Progress_moby21233) error
30 }
31
32 type chanOutput_moby21233 chan<- Progress_moby21233
33
34 type TransferManager_moby21233 struct {
35 mu sync.Mutex
36 }
37
38 type Transfer_moby21233 struct {
39 mu sync.Mutex
40 }
41
42 type Watcher_moby21233 struct {
43 signalChan chan struct{}
44 releaseChan chan struct{}
45 running chan struct{}
46 }
47
48 func ChanOutput_moby21233(progressChan chan<- Progress_moby21233) Output_moby21233 {
49 return chanOutput_moby21233(progressChan)
50 }
51 func (out chanOutput_moby21233) WriteProgress(p Progress_moby21233) error {
52 out <- p
53 return nil
54 }
55 func NewTransferManager_moby21233() *TransferManager_moby21233 {
56 return &TransferManager_moby21233{}
57 }
58 func NewTransfer_moby21233() *Transfer_moby21233 {
59 return &Transfer_moby21233{}
60 }
61 func (t *Transfer_moby21233) Release(watcher *Watcher_moby21233) {
62 t.mu.Lock()
63 t.mu.Unlock()
64 close(watcher.releaseChan)
65 <-watcher.running
66 }
67 func (t *Transfer_moby21233) Watch(progressOutput Output_moby21233) *Watcher_moby21233 {
68 t.mu.Lock()
69 defer t.mu.Unlock()
70 lastProgress := Progress_moby21233{}
71 w := &Watcher_moby21233{
72 releaseChan: make(chan struct{}),
73 signalChan: make(chan struct{}),
74 running: make(chan struct{}),
75 }
76 go func() {
77 defer func() {
78 close(w.running)
79 }()
80 done := false
81 for {
82 t.mu.Lock()
83 t.mu.Unlock()
84 if rand.Int31n(2) >= 1 {
85 progressOutput.WriteProgress(lastProgress)
86 }
87 if done {
88 return
89 }
90 select {
91 case <-w.signalChan:
92 case <-w.releaseChan:
93 done = true
94 }
95 }
96 }()
97 return w
98 }
99 func (tm *TransferManager_moby21233) Transfer(progressOutput Output_moby21233) (*Transfer_moby21233, *Watcher_moby21233) {
100 tm.mu.Lock()
101 defer tm.mu.Unlock()
102 t := NewTransfer_moby21233()
103 return t, t.Watch(progressOutput)
104 }
105
106 func testTransfer_moby21233() {
107 tm := NewTransferManager_moby21233()
108 progressChan := make(chan Progress_moby21233)
109 progressDone := make(chan struct{})
110 go func() {
111 time.Sleep(1 * time.Millisecond)
112 for p := range progressChan {
113 if rand.Int31n(2) >= 1 {
114 return
115 }
116 _ = p
117 }
118 close(progressDone)
119 }()
120 time.Sleep(1 * time.Millisecond)
121 ids := []string{"id1", "id2", "id3"}
122 xrefs := make([]*Transfer_moby21233, len(ids))
123 watchers := make([]*Watcher_moby21233, len(ids))
124 for i := range ids {
125 xrefs[i], watchers[i] = tm.Transfer(ChanOutput_moby21233(progressChan))
126 time.Sleep(2 * time.Millisecond)
127 }
128
129 for i := range xrefs {
130 xrefs[i].Release(watchers[i])
131 }
132
133 close(progressChan)
134 <-progressDone
135 }
136
137 func Moby21233() {
138 prof := pprof.Lookup("goroutineleak")
139 defer func() {
140 time.Sleep(100 * time.Millisecond)
141 prof.WriteTo(os.Stdout, 2)
142 }()
143 for i := 0; i < 100; i++ {
144 go testTransfer_moby21233()
145 }
146 }
147
View as plain text