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  }