| 1 | module eventbus |
| 2 | |
| 3 | pub type EventHandlerFn = fn (receiver voidptr, args voidptr, sender voidptr) |
| 4 | |
| 5 | pub struct Publisher[T] { |
| 6 | mut: |
| 7 | registry &Registry[T] = unsafe { nil } |
| 8 | } |
| 9 | |
| 10 | pub struct Subscriber[T] { |
| 11 | mut: |
| 12 | registry &Registry[T] = unsafe { nil } |
| 13 | } |
| 14 | |
| 15 | pub struct Registry[T] { |
| 16 | mut: |
| 17 | events []EventHandler[T] |
| 18 | } |
| 19 | |
| 20 | pub struct EventHandler[T] { |
| 21 | name T |
| 22 | handler EventHandlerFn = unsafe { nil } |
| 23 | receiver voidptr = unsafe { nil } |
| 24 | once bool |
| 25 | } |
| 26 | |
| 27 | pub struct EventBus[T] { |
| 28 | pub mut: |
| 29 | registry &Registry[T] = unsafe { nil } |
| 30 | publisher &Publisher[T] = unsafe { nil } |
| 31 | subscriber &Subscriber[T] = unsafe { nil } |
| 32 | } |
| 33 | |
| 34 | // EventBus.new[T] create a new eventbus with event type T. |
| 35 | pub fn EventBus.new[T]() &EventBus[T] { |
| 36 | registry := &Registry[T]{ |
| 37 | events: [] |
| 38 | } |
| 39 | return &EventBus[T]{registry, &Publisher[T]{registry}, &Subscriber[T]{registry}} |
| 40 | } |
| 41 | |
| 42 | // new[T] create a new eventbus with event type T. |
| 43 | pub fn new[T]() &EventBus[T] { |
| 44 | registry := &Registry[T]{ |
| 45 | events: [] |
| 46 | } |
| 47 | return &EventBus[T]{registry, &Publisher[T]{registry}, &Subscriber[T]{registry}} |
| 48 | } |
| 49 | |
| 50 | // publish publishes an event with provided Params & name. |
| 51 | pub fn (eb &EventBus[T]) publish(name T, sender voidptr, args voidptr) { |
| 52 | mut publisher := eb.publisher |
| 53 | publisher.publish(name, sender, args) |
| 54 | } |
| 55 | |
| 56 | // clear_all clears all subscribers. |
| 57 | pub fn (eb &EventBus[T]) clear_all() { |
| 58 | mut publisher := eb.publisher |
| 59 | publisher.clear_all() |
| 60 | } |
| 61 | |
| 62 | // has_subscriber check if a subscriber to an event exists. |
| 63 | pub fn (eb &EventBus[T]) has_subscriber(name T) bool { |
| 64 | return eb.registry.check_subscriber(name) |
| 65 | } |
| 66 | |
| 67 | const dedup_buffer_len = 20 |
| 68 | |
| 69 | // publish an event with provided Params & name. |
| 70 | fn (mut pb Publisher[T]) publish(name T, sender voidptr, args voidptr) { |
| 71 | // println('Publisher.publish(name=${name} sender=${sender} args=${args})') |
| 72 | invalid := 0 |
| 73 | mut handled_receivers := unsafe { [dedup_buffer_len]voidptr{init: &invalid} } // handle duplicate bugs TODO fix properly + perf |
| 74 | mut j := 0 |
| 75 | mut found_onces := 0 |
| 76 | for event in pb.registry.events { |
| 77 | if event.name == name { |
| 78 | if event.once { |
| 79 | found_onces++ |
| 80 | } |
| 81 | if event.receiver in handled_receivers { |
| 82 | continue |
| 83 | } |
| 84 | event.handler(event.receiver, args, sender) |
| 85 | handled_receivers[j] = event.receiver |
| 86 | j = (j + 1) % dedup_buffer_len |
| 87 | } |
| 88 | } |
| 89 | if found_onces > 0 { |
| 90 | pb.registry.events = pb.registry.events.filter(!(it.name == name && it.once)) |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | // clear_all clear all subscribers. |
| 95 | fn (mut p Publisher[T]) clear_all() { |
| 96 | p.registry.events.clear() |
| 97 | } |
| 98 | |
| 99 | // subscribe subscribe to an event `name`. |
| 100 | pub fn (mut s Subscriber[T]) subscribe(name T, handler EventHandlerFn) { |
| 101 | s.registry.events << EventHandler[T]{ |
| 102 | name: name |
| 103 | handler: handler |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | // subscribe_method subscribe to an event `name` and also set the `receiver` as a parameter. |
| 108 | pub fn (mut s Subscriber[T]) subscribe_method(name T, handler EventHandlerFn, receiver voidptr) { |
| 109 | s.registry.events << EventHandler[T]{ |
| 110 | name: name |
| 111 | handler: handler |
| 112 | receiver: receiver |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | // unsubscribe_method unsubscribe a receiver for only one method. |
| 117 | pub fn (mut s Subscriber[T]) unsubscribe_method(name T, receiver voidptr) { |
| 118 | s.registry.events = s.registry.events.filter(!(it.name == name && it.receiver == receiver)) |
| 119 | } |
| 120 | |
| 121 | // unsubscribe_receiver unsubscribes a receiver from all events. |
| 122 | pub fn (mut s Subscriber[T]) unsubscribe_receiver(receiver voidptr) { |
| 123 | s.registry.events = s.registry.events.filter(it.receiver != receiver) |
| 124 | } |
| 125 | |
| 126 | // subscribe_once subscribe only once to an event `name`. |
| 127 | pub fn (mut s Subscriber[T]) subscribe_once(name T, handler EventHandlerFn) { |
| 128 | s.registry.events << EventHandler[T]{ |
| 129 | name: name |
| 130 | handler: handler |
| 131 | once: true |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | // is_subscribed check if we are subscribed to an event `name`. |
| 136 | pub fn (s &Subscriber[T]) is_subscribed(name T) bool { |
| 137 | return s.registry.check_subscriber(name) |
| 138 | } |
| 139 | |
| 140 | // is_subscribed_method checks whether a receiver was already subscribed for any events. |
| 141 | pub fn (s &Subscriber[T]) is_subscribed_method(name T, receiver voidptr) bool { |
| 142 | return s.registry.events.any(it.name == name && it.receiver == receiver) |
| 143 | } |
| 144 | |
| 145 | // unsubscribe unsubscribe from an event `name`. |
| 146 | pub fn (mut s Subscriber[T]) unsubscribe(name T, handler EventHandlerFn) { |
| 147 | // v := voidptr(handler) |
| 148 | s.registry.events = s.registry.events.filter(!(it.name == name && it.handler == handler)) |
| 149 | } |
| 150 | |
| 151 | // Registry Methods |
| 152 | fn (r &Registry[T]) check_subscriber(name T) bool { |
| 153 | return r.events.any(it.name == name) |
| 154 | } |
| 155 | |