github.com/jmigpin/editor@v1.6.0/util/ctxutil/watchdone.go (about) 1 package ctxutil 2 3 import ( 4 "context" 5 "sync" 6 ) 7 8 func WatchDone(cancel func(), ctx context.Context) func() { 9 ch := make(chan struct{}, 1) // 1=receive clearwatching if ctx already done 10 11 // ensure sync with the receiver, otherwise clearwatching could be called and exit and the ctx.done be called later on the same goroutine and still arrive before the clearwatching signal 12 var cancelMu sync.Mutex 13 14 go func() { 15 select { 16 case <-ch: // release goroutine on clearwatching() 17 case <-ctx.Done(): 18 cancelMu.Lock() 19 if cancel != nil { // could be cleared already by clearwatching() 20 cancel() 21 } 22 cancelMu.Unlock() 23 } 24 }() 25 26 clearWatching := func() { 27 cancelMu.Lock() 28 cancel = nil 29 cancelMu.Unlock() 30 ch <- struct{}{} // send to release goroutine 31 } 32 33 return clearWatching 34 }