eventbus: refactoring; add unsubscribe_method and unsubscribe_receiver (#9443)

pull/9536/head
Andréas Livet 2021-03-30 14:32:24 +02:00 committed by GitHub
parent d1fadaf30c
commit 205fb88d90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 34 deletions

View File

@ -35,11 +35,7 @@ pub fn new() &EventBus {
registry := &Registry{ registry := &Registry{
events: [] events: []
} }
return &EventBus{ return &EventBus{registry, &Publisher{registry}, &Subscriber{registry}}
registry,&Publisher{
registry},&Subscriber{
registry}
}
} }
// EventBus Methods // EventBus Methods
@ -59,23 +55,16 @@ pub fn (eb &EventBus) has_subscriber(name string) bool {
// Publisher Methods // Publisher Methods
fn (mut pb Publisher) publish(name string, sender voidptr, args voidptr) { 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.name == name {
if event.once {
pb.registry.events.delete(i)
}
event.handler(event.receiver, args, sender) event.handler(event.receiver, args, sender)
} }
} }
pb.registry.events = pb.registry.events.filter(!(it.name == name && it.once))
} }
fn (mut p Publisher) clear_all() { fn (mut p Publisher) clear_all() {
if p.registry.events.len == 0 { p.registry.events.clear()
return
}
for i := p.registry.events.len - 1; i >= 0; i-- {
p.registry.events.delete(i)
}
} }
// Subscriber Methods // Subscriber Methods
@ -94,6 +83,16 @@ pub fn (mut s Subscriber) subscribe_method(name string, handler EventHandlerFn,
} }
} }
// 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) { pub fn (mut s Subscriber) subscribe_once(name string, handler EventHandlerFn) {
s.registry.events << EventHandler{ s.registry.events << EventHandler{
name: name name: name
@ -106,23 +105,19 @@ pub fn (s &Subscriber) is_subscribed(name string) bool {
return s.registry.check_subscriber(name) 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) { pub fn (mut s Subscriber) unsubscribe(name string, handler EventHandlerFn) {
// v := voidptr(handler) // v := voidptr(handler)
for i, event in s.registry.events { s.registry.events = s.registry.events.filter(!(it.name == name && it.handler == handler))
if event.name == name {
if event.handler == handler {
s.registry.events.delete(i)
}
}
}
} }
// Registry Methods // Registry Methods
fn (r &Registry) check_subscriber(name string) bool { fn (r &Registry) check_subscriber(name string) bool {
for event in r.events { return r.events.any(it.name == name)
if event.name == name {
return true
}
}
return false
} }

View File

@ -4,6 +4,10 @@ struct EventData {
data string data string
} }
struct FakeReceiver {
ok bool
}
fn test_eventbus() { fn test_eventbus() {
ev_data := &EventData{'hello'} ev_data := &EventData{'hello'}
mut eb := eventbus.new() mut eb := eventbus.new()
@ -21,8 +25,85 @@ fn test_eventbus() {
assert !eb.subscriber.is_subscribed('on_test') 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) { fn on_test(receiver voidptr, ev &EventData, sender voidptr) {
assert receiver == 0 assert receiver == 0
assert sender != 0 assert sender != 0
assert ev.data == 'hello' 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'
}