11package EventBus
22
33import (
4- "reflect"
54 "sync"
65)
76
7+ type SubscriptionRef uint64
8+
89// SimpleBusSubscriber defines subscription-related bus behavior for event of specific type T
910type SimpleBusSubscriber [T any ] interface {
10- Subscribe (topic string , fn func (T ))
11- SubscribeAsync (topic string , fn func (T ), transactional bool )
12- SubscribeOnce (topic string , fn func (T ))
13- SubscribeOnceAsync (topic string , fn func (T ))
14- Unsubscribe (topic string , handler func ( T ) )
11+ Subscribe (topic string , fn func (T )) SubscriptionRef
12+ SubscribeAsync (topic string , fn func (T ), transactional bool ) SubscriptionRef
13+ SubscribeOnce (topic string , fn func (T )) SubscriptionRef
14+ SubscribeOnceAsync (topic string , fn func (T )) SubscriptionRef
15+ Unsubscribe (topic string , ref SubscriptionRef )
1516}
1617
1718// SimpleBusPublisher defines publishing-related bus behavior for event of specific type T
@@ -26,16 +27,12 @@ type SimpleBus[T any] interface {
2627 SimpleBusPublisher [T ]
2728}
2829
29- type callBack [T any ] struct {
30- Call func (T )
31- pointer uintptr
32- }
33-
3430type genericHandler [T any ] struct {
35- callBack callBack [ T ]
31+ callBack func ( T )
3632 once bool
3733 async bool
3834 transactional bool
35+ reference SubscriptionRef
3936 sync.Mutex // lock for an event handler - useful for running async callbacks serially
4037}
4138
@@ -48,37 +45,28 @@ func (h *genericHandler[T]) Call(arg T, wg *sync.WaitGroup) {
4845 h .Lock ()
4946 defer h .Unlock ()
5047 }
51- h .callBack . Call (arg )
48+ h .callBack (arg )
5249 }()
5350 return
5451 } else {
55- h .callBack . Call (arg )
52+ h .callBack (arg )
5653 }
5754}
5855
59- type listeners [T any ] [ ]* genericHandler [T ]
56+ type listeners [T any ] map [ SubscriptionRef ]* genericHandler [T ]
6057
61- func (l * listeners [T ]) add (handler * genericHandler [T ]) {
62- for _ , h := range * l {
63- if h .callBack .pointer == handler .callBack .pointer {
64- return
65- }
66- }
67- * l = append (* l , handler )
58+ func (l listeners [T ]) add (handler * genericHandler [T ]) {
59+ l [handler .reference ] = handler
6860}
6961
70- func (l * listeners [T ]) delete (handler * genericHandler [T ]) {
71- for i , h := range * l {
72- if h .callBack .pointer == handler .callBack .pointer {
73- * l = append ((* l )[:i ], (* l )[i + 1 :]... )
74- return
75- }
76- }
62+ func (l listeners [_ ]) delete (ref SubscriptionRef ) {
63+ delete (l , ref )
7764}
7865
79- func newGenericHandler [T any ](fn func (T ), async , transactional , once bool ) * genericHandler [T ] {
66+ func newGenericHandler [T any ](fn func (T ), ref SubscriptionRef , async , transactional , once bool ) * genericHandler [T ] {
8067 return & genericHandler [T ]{
81- callBack : callBack [T ]{Call : fn , pointer : reflect .ValueOf (fn ).Pointer ()},
68+ callBack : fn ,
69+ reference : ref ,
8270 async : async ,
8371 transactional : transactional ,
8472 once : once ,
@@ -87,13 +75,15 @@ func newGenericHandler[T any](fn func(T), async, transactional, once bool) *gene
8775
8876type GenericBus [T any ] struct {
8977 handlers map [string ]* listeners [T ]
78+ lastRef SubscriptionRef
9079 sync.RWMutex
9180 wg sync.WaitGroup
9281}
9382
9483func NewSimpleBus [T any ]() SimpleBus [T ] {
9584 return & GenericBus [T ]{
9685 handlers : make (map [string ]* listeners [T ]),
86+ lastRef : SubscriptionRef (0 ),
9787 }
9888}
9989
@@ -104,27 +94,27 @@ func (bus *GenericBus[_]) HasCallback(topic string) bool {
10494 return ok && len (* bus .handlers [topic ]) > 0
10595}
10696
107- func (bus * GenericBus [T ]) Subscribe (topic string , fn func (T )) {
108- bus .subscribe (topic , fn , false , false , false )
97+ func (bus * GenericBus [T ]) Subscribe (topic string , fn func (T )) SubscriptionRef {
98+ return bus .subscribe (topic , fn , false , false , false )
10999}
110100
111- func (bus * GenericBus [T ]) SubscribeOnce (topic string , fn func (T )) {
112- bus .subscribe (topic , fn , false , false , true )
101+ func (bus * GenericBus [T ]) SubscribeOnce (topic string , fn func (T )) SubscriptionRef {
102+ return bus .subscribe (topic , fn , false , false , true )
113103}
114104
115- func (bus * GenericBus [T ]) SubscribeOnceAsync (topic string , fn func (T )) {
116- bus .subscribe (topic , fn , true , false , true )
105+ func (bus * GenericBus [T ]) SubscribeOnceAsync (topic string , fn func (T )) SubscriptionRef {
106+ return bus .subscribe (topic , fn , true , false , true )
117107}
118108
119- func (bus * GenericBus [T ]) SubscribeAsync (topic string , fn func (T ), transactional bool ) {
120- bus .subscribe (topic , fn , true , transactional , false )
109+ func (bus * GenericBus [T ]) SubscribeAsync (topic string , fn func (T ), transactional bool ) SubscriptionRef {
110+ return bus .subscribe (topic , fn , true , transactional , false )
121111}
122112
123- func (bus * GenericBus [T ]) Unsubscribe (topic string , fn func ( T ) ) {
113+ func (bus * GenericBus [T ]) Unsubscribe (topic string , ref SubscriptionRef ) {
124114 bus .Lock ()
125115 defer bus .Unlock ()
126116 if _ , ok := bus .handlers [topic ]; ok {
127- bus .handlers [topic ].delete (newGenericHandler ( fn , false , false , false ) )
117+ bus .handlers [topic ].delete (ref )
128118 }
129119}
130120
@@ -135,7 +125,7 @@ func (bus *GenericBus[T]) Publish(topic string, arg T) {
135125 for _ , subscriber := range * subscribers {
136126 fire <- subscriber
137127 if subscriber .once {
138- bus .handlers [topic ].delete (subscriber )
128+ bus .handlers [topic ].delete (subscriber . reference )
139129 }
140130 }
141131 bus .Unlock ()
@@ -151,13 +141,15 @@ func (bus *GenericBus[T]) WaitAsync() {
151141 bus .wg .Wait ()
152142}
153143
154- func (bus * GenericBus [T ]) subscribe (topic string , fn func (T ), async , transactional , once bool ) {
144+ func (bus * GenericBus [T ]) subscribe (topic string , fn func (T ), async , transactional , once bool ) SubscriptionRef {
155145 bus .Lock ()
156146 defer bus .Unlock ()
147+ bus .lastRef ++
157148 if _ , ok := bus .handlers [topic ]; ! ok {
158149 bus .handlers [topic ] = & listeners [T ]{}
159150 }
160- bus .handlers [topic ].add (newGenericHandler (fn , async , transactional , once ))
151+ bus .handlers [topic ].add (newGenericHandler (fn , bus .lastRef , async , transactional , once ))
152+ return bus .lastRef
161153}
162154
163155func (bus * GenericBus [T ]) fetchSubscribers (topic string ) (* listeners [T ], bool ) {
0 commit comments