v8.run/go/exp@v0.0.26-0.20230226010534-afcdbd3f782d/broadcast/evbus/evbus.go (about)

     1  package evbus
     2  
     3  import (
     4  	"strconv"
     5  	"sync"
     6  	"sync/atomic"
     7  
     8  	"v8.run/go/exp/broadcast"
     9  )
    10  
    11  var evbus_map sync.Map
    12  
    13  func Publish[T any](topic string, v T) {
    14  	t, ok := evbus_map.Load(topic)
    15  	if !ok || t == nil {
    16  		t, _ = evbus_map.LoadOrStore(topic, broadcast.NewTopic[any]())
    17  	}
    18  	t.(*broadcast.Topic[any]).Broadcast(v)
    19  }
    20  
    21  type Subscription struct {
    22  	topic string
    23  	s     *broadcast.Subscription[any]
    24  	stop  atomic.Uint32
    25  }
    26  
    27  func Subscribe[T any](topic string, fn func(v T) (Unsubscribe bool)) *Subscription {
    28  	t, ok := evbus_map.Load(topic)
    29  	if !ok || t == nil {
    30  		t, _ = evbus_map.LoadOrStore(topic, broadcast.NewTopic[any]())
    31  	}
    32  	var ss Subscription
    33  	ss.topic = topic
    34  
    35  	ss.s = t.(*broadcast.Topic[any]).Subscribe(func(v any) {
    36  		if ss.stop.Load() == 1 {
    37  			return
    38  		}
    39  
    40  		if val, ok := v.(T); ok {
    41  			unsub := fn(val)
    42  			if unsub {
    43  				ss.Unsubscribe()
    44  			}
    45  		}
    46  	})
    47  
    48  	return &ss
    49  }
    50  
    51  func (ss *Subscription) Unsubscribe() {
    52  	if ss.stop.CompareAndSwap(0, 1) {
    53  		go ss.s.Unsubscribe()
    54  	}
    55  }
    56  
    57  func (ss *Subscription) String() string {
    58  	return "<Subscription " + strconv.Quote(ss.topic) + " >"
    59  }