github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/state/raft/wait.go (about)

     1  package raft
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  )
     7  
     8  type waitItem struct {
     9  	// channel to wait up the waiter
    10  	ch chan interface{}
    11  	// callback which is called synchronously when the wait is triggered
    12  	cb func()
    13  	// callback which is called to cancel a waiter
    14  	cancel func()
    15  }
    16  
    17  type wait struct {
    18  	l sync.Mutex
    19  	m map[uint64]waitItem
    20  }
    21  
    22  func newWait() *wait {
    23  	return &wait{m: make(map[uint64]waitItem)}
    24  }
    25  
    26  func (w *wait) register(id uint64, cb func(), cancel func()) <-chan interface{} {
    27  	w.l.Lock()
    28  	defer w.l.Unlock()
    29  	_, ok := w.m[id]
    30  	if !ok {
    31  		ch := make(chan interface{}, 1)
    32  		w.m[id] = waitItem{ch: ch, cb: cb, cancel: cancel}
    33  		return ch
    34  	}
    35  	panic(fmt.Sprintf("duplicate id %x", id))
    36  }
    37  
    38  func (w *wait) trigger(id uint64, x interface{}) bool {
    39  	w.l.Lock()
    40  	waitItem, ok := w.m[id]
    41  	delete(w.m, id)
    42  	w.l.Unlock()
    43  	if ok {
    44  		if waitItem.cb != nil {
    45  			waitItem.cb()
    46  		}
    47  		waitItem.ch <- x
    48  		return true
    49  	}
    50  	return false
    51  }
    52  
    53  func (w *wait) cancel(id uint64) {
    54  	w.l.Lock()
    55  	waitItem, ok := w.m[id]
    56  	delete(w.m, id)
    57  	w.l.Unlock()
    58  	if ok {
    59  		if waitItem.cancel != nil {
    60  			waitItem.cancel()
    61  		}
    62  		close(waitItem.ch)
    63  	}
    64  }
    65  
    66  func (w *wait) cancelAll() {
    67  	w.l.Lock()
    68  	defer w.l.Unlock()
    69  
    70  	for id, waitItem := range w.m {
    71  		delete(w.m, id)
    72  		if waitItem.cancel != nil {
    73  			waitItem.cancel()
    74  		}
    75  		close(waitItem.ch)
    76  	}
    77  }