@@ -110,6 +110,8 @@ func (f *Fifo) run() {
110110 close (f .resume )
111111 }()
112112
113+ async := newAsync (f .ctx , f .PanicHandler )
114+
113115 for {
114116 var job Job
115117 f .mu .Lock ()
@@ -128,15 +130,13 @@ func (f *Fifo) run() {
128130 f .mu .Unlock ()
129131 // clean up pending jobs
130132 for _ , job := range pendings {
131- done := asyncDo (f .ctx , f .PanicHandler , job )
132- <- done
133+ async .Do (job )
133134 }
135+ async .Close ()
134136 return
135137 }
136138 } else {
137- done := asyncDo (f .ctx , f .PanicHandler , job )
138- <- done
139-
139+ async .Do (job )
140140 f .finishCond .L .Lock ()
141141 f .finished ++
142142 f .pendings = f .pendings [1 :]
@@ -146,18 +146,45 @@ func (f *Fifo) run() {
146146 }
147147}
148148
149- // AsyncDo is a basic promise implementation: it wraps calls a function in a goroutine
150- func asyncDo (ctx context.Context , panicHandler func (stack DebugStack ), f func (ctx context.Context )) <- chan struct {} {
151- ch := make (chan struct {}, 1 )
152- go func (ch chan struct {}, ctx context.Context , panicHandler func (stack DebugStack )) {
153- defer func () {
154- if err := recover (); err != nil {
155- panicHandler (DebugStack (debug .Stack ()))
156- }
157- }()
149+ func newAsync (ctx context.Context , panicHandler func (stack DebugStack )) * async {
150+ a := & async {
151+ Ctx : ctx ,
152+ PanicHandler : panicHandler ,
153+ Jobs : make (chan func (ctx context.Context )),
154+ }
155+ a .init ()
156+ return a
157+ }
158+
159+ type async struct {
160+ Ctx context.Context
161+ Jobs chan func (ctx context.Context )
162+ PanicHandler func (stack DebugStack )
163+ }
164+
165+ func (a * async ) init () {
166+ go func (jobs chan func (ctx context.Context ), ctx context.Context , panicHandler func (stack DebugStack )) {
167+ for job := range jobs {
168+ do (job , ctx , panicHandler )
169+ }
170+ }(a .Jobs , a .Ctx , a .PanicHandler )
171+ }
172+
173+ func (a * async ) Do (f func (ctx context.Context )) {
174+ a .Jobs <- f
175+ }
176+
177+ func (a * async ) Close () {
178+ close (a .Jobs )
179+ }
180+
181+ func do (job func (ctx context.Context ), ctx context.Context , panicHandler func (stack DebugStack )) {
182+
183+ defer func () {
184+ if err := recover (); err != nil {
185+ panicHandler (DebugStack (debug .Stack ()))
186+ }
187+ }()
158188
159- f (ctx )
160- ch <- struct {}{}
161- }(ch , ctx , panicHandler )
162- return ch
189+ job (ctx )
163190}
0 commit comments