GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

44 lines
888 B

  1. package notifier
  2. import (
  3. "context"
  4. "sync"
  5. )
  6. // A Notifier is a synchronization primitive for waking upp all listeners at once.
  7. type Notifier struct {
  8. mutex sync.Mutex
  9. ch chan struct{}
  10. }
  11. // Broadcast wakes all listeners if there are any.
  12. func (notifier *Notifier) Broadcast() {
  13. notifier.mutex.Lock()
  14. if notifier.ch != nil {
  15. close(notifier.ch)
  16. notifier.ch = nil
  17. }
  18. notifier.mutex.Unlock()
  19. }
  20. // C gets the channel that'll close on the next notification.
  21. func (notifier *Notifier) C() <-chan struct{} {
  22. notifier.mutex.Lock()
  23. if notifier.ch == nil {
  24. notifier.ch = make(chan struct{})
  25. }
  26. ch := notifier.ch
  27. notifier.mutex.Unlock()
  28. return ch
  29. }
  30. // Wait waits for the next `Broadcast` call, or the context's termination.
  31. func (notifier *Notifier) Wait(ctx context.Context) error {
  32. select {
  33. case <-notifier.C():
  34. return nil
  35. case <-ctx.Done():
  36. return ctx.Err()
  37. }
  38. }