eventbus: refactoring; add unsubscribe_method and unsubscribe_receiver (#9443)
							parent
							
								
									d1fadaf30c
								
							
						
					
					
						commit
						205fb88d90
					
				|  | @ -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) | ||||
| } | ||||
|  |  | |||
|  | @ -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' | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue