callback.go 908 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package utils
  2. import (
  3. "io"
  4. "sync"
  5. list "github.com/bahlo/generic-list-go"
  6. )
  7. type Callback[T any] struct {
  8. list list.List[func(T)]
  9. mutex sync.RWMutex
  10. }
  11. func NewCallback[T any]() *Callback[T] {
  12. return &Callback[T]{}
  13. }
  14. func (c *Callback[T]) Register(item func(T)) io.Closer {
  15. c.mutex.Lock()
  16. defer c.mutex.Unlock()
  17. element := c.list.PushBack(item)
  18. return &callbackCloser[T]{
  19. element: element,
  20. callback: c,
  21. }
  22. }
  23. func (c *Callback[T]) Emit(item T) {
  24. c.mutex.RLock()
  25. defer c.mutex.RUnlock()
  26. for element := c.list.Front(); element != nil; element = element.Next() {
  27. go element.Value(item)
  28. }
  29. }
  30. type callbackCloser[T any] struct {
  31. element *list.Element[func(T)]
  32. callback *Callback[T]
  33. once sync.Once
  34. }
  35. func (c *callbackCloser[T]) Close() error {
  36. c.once.Do(func() {
  37. c.callback.mutex.Lock()
  38. defer c.callback.mutex.Unlock()
  39. c.callback.list.Remove(c.element)
  40. })
  41. return nil
  42. }