From 205fb88d9081cf9bdabe9f34b8bc947d7a8232b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9as=20Livet?= Date: Tue, 30 Mar 2021 14:32:24 +0200 Subject: [PATCH] eventbus: refactoring; add unsubscribe_method and unsubscribe_receiver (#9443) --- vlib/eventbus/eventbus.v | 63 +++++++++++++-------------- vlib/eventbus/eventbus_test.v | 81 +++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 34 deletions(-) diff --git a/vlib/eventbus/eventbus.v b/vlib/eventbus/eventbus.v index 0d8c1e3816..fbcdf7478c 100644 --- a/vlib/eventbus/eventbus.v +++ b/vlib/eventbus/eventbus.v @@ -18,10 +18,10 @@ mut: } struct EventHandler { - name string - handler EventHandlerFn + name string + handler EventHandlerFn receiver voidptr = voidptr(0) - once bool + once bool } pub struct EventBus { @@ -35,11 +35,7 @@ pub fn new() &EventBus { registry := &Registry{ events: [] } - return &EventBus{ - registry,&Publisher{ - registry},&Subscriber{ - registry} - } + return &EventBus{registry, &Publisher{registry}, &Subscriber{registry}} } // EventBus Methods @@ -59,43 +55,46 @@ pub fn (eb &EventBus) has_subscriber(name string) bool { // Publisher Methods fn (mut pb Publisher) publish(name string, sender voidptr, args voidptr) { - for i, event in pb.registry.events { + for event in pb.registry.events { if event.name == name { - if event.once { - pb.registry.events.delete(i) - } event.handler(event.receiver, args, sender) } } + pb.registry.events = pb.registry.events.filter(!(it.name == name && it.once)) } fn (mut p Publisher) clear_all() { - if p.registry.events.len == 0 { - return - } - for i := p.registry.events.len - 1; i >= 0; i-- { - p.registry.events.delete(i) - } + p.registry.events.clear() } // Subscriber Methods pub fn (mut s Subscriber) subscribe(name string, handler EventHandlerFn) { - s.registry.events << EventHandler { + s.registry.events << EventHandler{ name: name handler: handler } } pub fn (mut s Subscriber) subscribe_method(name string, handler EventHandlerFn, receiver voidptr) { - s.registry.events << EventHandler { + s.registry.events << EventHandler{ name: name handler: handler receiver: receiver } } +// unsubscribe_method unsubscribe a receiver for only one method +pub fn (mut s Subscriber) unsubscribe_method(name string, receiver voidptr) { + s.registry.events = s.registry.events.filter(!(it.name == name && it.receiver == receiver)) +} + +// unsubscribe_receiver unsubscribes a receiver from all events +pub fn (mut s Subscriber) unsubscribe_receiver(receiver voidptr) { + s.registry.events = s.registry.events.filter(it.receiver != receiver) +} + pub fn (mut s Subscriber) subscribe_once(name string, handler EventHandlerFn) { - s.registry.events << EventHandler { + s.registry.events << EventHandler{ name: name handler: handler once: true @@ -106,23 +105,19 @@ pub fn (s &Subscriber) is_subscribed(name string) bool { return s.registry.check_subscriber(name) } + + +// is_subscribed_method checks whether a receiver was already subscribed for any events +pub fn (s &Subscriber) is_subscribed_method(name string, receiver voidptr) bool { + return s.registry.events.any(it.name == name && it.receiver == receiver) +} + pub fn (mut s Subscriber) unsubscribe(name string, handler EventHandlerFn) { // v := voidptr(handler) - for i, event in s.registry.events { - if event.name == name { - if event.handler == handler { - s.registry.events.delete(i) - } - } - } + s.registry.events = s.registry.events.filter(!(it.name == name && it.handler == handler)) } // Registry Methods fn (r &Registry) check_subscriber(name string) bool { - for event in r.events { - if event.name == name { - return true - } - } - return false + return r.events.any(it.name == name) } diff --git a/vlib/eventbus/eventbus_test.v b/vlib/eventbus/eventbus_test.v index 30be95b7d5..e27af886fe 100644 --- a/vlib/eventbus/eventbus_test.v +++ b/vlib/eventbus/eventbus_test.v @@ -4,6 +4,10 @@ struct EventData { data string } +struct FakeReceiver { + ok bool +} + fn test_eventbus() { ev_data := &EventData{'hello'} mut eb := eventbus.new() @@ -21,8 +25,85 @@ fn test_eventbus() { assert !eb.subscriber.is_subscribed('on_test') } +fn test_subscribe_method() { + // Does not really test subscribe_method idinvidually though + // given + mut eb := eventbus.new() + r := FakeReceiver{} + + assert !eb.subscriber.is_subscribed_method('on_test_with_receiver', r) + // when + eb.subscriber.subscribe_method('on_test_with_receiver', on_test_with_receiver, r) + + // then + assert eb.subscriber.is_subscribed_method('on_test_with_receiver', r) +} + +fn test_unsubscribe_method() { + // given + mut eb := eventbus.new() + r := FakeReceiver{} + r2 := FakeReceiver{} + + // when + eb.subscriber.subscribe_method('on_test_with_receiver', on_test_with_receiver, r) + eb.subscriber.subscribe_method('on_test_with_receiver', on_test_with_receiver, r2) + eb.subscriber.unsubscribe_method('on_test_with_receiver', r) + + // then + assert !eb.subscriber.is_subscribed_method('on_test_with_receiver', r) + assert eb.subscriber.is_subscribed_method('on_test_with_receiver', r2) +} + +fn test_publish() { + // given + ev_data := &EventData{'hello'} + mut eb := eventbus.new() + + // when + eb.subscriber.subscribe_once('on_test', on_test) + eb.subscriber.subscribe_once('on_test', on_test) + eb.publish('on_test', eb, ev_data) + + // then + assert !eb.subscriber.is_subscribed('on_test') +} + +fn test_publish_with_receiver() { + // given + mut eb := eventbus.new() + ev_data := &EventData{'hello'} + r := FakeReceiver{} + + // when + eb.subscriber.subscribe_method('on_test_with_receiver', on_test_with_receiver, r) + eb.publish('on_test_with_receiver', eb, ev_data) + + // then asserts are in on_test_with_receiver, don't know how to be sure + // that it has been properly called... +} + +fn test_unsubscribe_reveiver() { + // given + mut eb := eventbus.new() + r := &FakeReceiver{} + + // when + eb.subscriber.subscribe_method('on_test_with_receiver', on_test_with_receiver, r) + eb.subscriber.subscribe_method('on_test', on_test, r) + eb.subscriber.unsubscribe_receiver(r) + assert !eb.subscriber.is_subscribed_method('on_test_with_receiver', r) + assert !eb.subscriber.is_subscribed_method('on_test', r) +} + fn on_test(receiver voidptr, ev &EventData, sender voidptr) { assert receiver == 0 assert sender != 0 assert ev.data == 'hello' } + +fn on_test_with_receiver(receiver &FakeReceiver, ev &EventData, sender voidptr) { + assert receiver.ok == false + assert sender != 0 + assert ev.data == 'hello' +}