github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/notifier.go (about)

     1  package engine
     2  
     3  // Notifier is a concurrency primitive for informing worker routines about the
     4  // arrival of new work unit(s). Notifiers essentially behave like
     5  // channels in that they can be passed by value and still allow concurrent
     6  // updates of the same internal state.
     7  type Notifier struct {
     8  	// Illustrative description of the Notifier:
     9  	// * When the gate is activated, it will let a _single_  person step through the gate.
    10  	// * When somebody steps through the gate, it deactivates (atomic operation) and
    11  	//   prevents subsequent people from passing (until it is activated again).
    12  	// * The gate has a memory and remembers whether it is activated. I.e. the gate
    13  	//   can be activated while no-one is waiting. When a person arrives later, they
    14  	//   can pass through the gate.
    15  	// * Activating an already-activated gate is a no-op.
    16  	//
    17  	// Implementation:
    18  	// We implement the Notifier using a channel. Activating the gate corresponds to
    19  	// calling `Notify()` on the Notifier, which pushes an element to the channel.
    20  	// Passing through the gate corresponds to receiving from the `Channel()`.
    21  	// As we don't want the routine sending the notification to wait until a worker
    22  	// routine reads from the channel, we need a buffered channel with capacity 1.
    23  
    24  	notifier chan struct{} // buffered channel with capacity 1
    25  }
    26  
    27  // NewNotifier instantiates a Notifier. Notifiers essentially behave like
    28  // channels in that they can be passed by value and still allow concurrent
    29  // updates of the same internal state.
    30  func NewNotifier() Notifier {
    31  	return Notifier{make(chan struct{}, 1)}
    32  }
    33  
    34  // Notify sends a notification
    35  func (n Notifier) Notify() {
    36  	select {
    37  	// to prevent from getting blocked by dropping the notification if
    38  	// there is no handler subscribing the channel.
    39  	case n.notifier <- struct{}{}:
    40  	default:
    41  	}
    42  }
    43  
    44  // Channel returns a channel for receiving notifications
    45  func (n Notifier) Channel() <-chan struct{} {
    46  	return n.notifier
    47  }