1
2
3
4
5 package main
6
7 import (
8 "os"
9 "runtime"
10 "runtime/pprof"
11 "sync"
12 "time"
13 )
14
15 func init() {
16 register("Serving2137", Serving2137)
17 }
18
19 type token_serving2137 struct{}
20
21 type request_serving2137 struct {
22 lock *sync.Mutex
23 accepted chan bool
24 }
25
26 type Breaker_serving2137 struct {
27 pendingRequests chan token_serving2137
28 activeRequests chan token_serving2137
29 }
30
31 func (b *Breaker_serving2137) Maybe(thunk func()) bool {
32 var t token_serving2137
33 select {
34 default:
35
36 return false
37 case b.pendingRequests <- t:
38
39
40 b.activeRequests <- t
41
42 defer func() {
43 <-b.activeRequests
44 runtime.Gosched()
45 <-b.pendingRequests
46 }()
47
48 thunk()
49
50 return true
51 }
52 }
53
54 func (b *Breaker_serving2137) concurrentRequest() request_serving2137 {
55 r := request_serving2137{lock: &sync.Mutex{}, accepted: make(chan bool, 1)}
56 r.lock.Lock()
57 var start sync.WaitGroup
58 start.Add(1)
59 go func() {
60 start.Done()
61 runtime.Gosched()
62 ok := b.Maybe(func() {
63
64 r.lock.Lock()
65 runtime.Gosched()
66 r.lock.Unlock()
67 })
68 r.accepted <- ok
69 }()
70 start.Wait()
71 return r
72 }
73
74
75
76 func (b *Breaker_serving2137) concurrentRequests(n int) []request_serving2137 {
77 requests := make([]request_serving2137, n)
78 for i := range requests {
79 requests[i] = b.concurrentRequest()
80 }
81 return requests
82 }
83
84 func NewBreaker_serving2137(queueDepth, maxConcurrency int32) *Breaker_serving2137 {
85 return &Breaker_serving2137{
86 pendingRequests: make(chan token_serving2137, queueDepth+maxConcurrency),
87 activeRequests: make(chan token_serving2137, maxConcurrency),
88 }
89 }
90
91 func unlock_serving2137(req request_serving2137) {
92 req.lock.Unlock()
93 runtime.Gosched()
94
95 ok := <-req.accepted
96 runtime.Gosched()
97
98 req.accepted <- ok
99 }
100
101 func unlockAll_serving2137(requests []request_serving2137) {
102 for _, lc := range requests {
103 unlock_serving2137(lc)
104 }
105 }
106
107 func Serving2137() {
108 prof := pprof.Lookup("goroutineleak")
109 defer func() {
110 time.Sleep(100 * time.Millisecond)
111 prof.WriteTo(os.Stdout, 2)
112 }()
113
114 for i := 0; i < 1000; i++ {
115 go func() {
116 b := NewBreaker_serving2137(1, 1)
117
118 locks := b.concurrentRequests(2)
119 unlockAll_serving2137(locks)
120 }()
121 }
122 }
123
View as plain text