EventBus 2.0.0

This commit is contained in:
Dawid Drozd 2017-08-06 11:22:59 +02:00
parent 630e220d43
commit 94973b5779
14 changed files with 411 additions and 112 deletions

View File

@ -2,15 +2,13 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.6 FATAL_ERROR)
# BUILD_SHARED_LIBS can controll build type!
PROJECT(EventBus
VERSION 1.1.0
VERSION 2.0.0
LANGUAGES CXX
)
ADD_LIBRARY(EventBus
src/eventbus/EventCollector.cpp include/eventbus/EventCollector.h
src/eventbus/Notification.cpp include/eventbus/Notification.h
include/eventbus/Notification2.h
include/eventbus/Notifier.h
include/eventbus/Event.h
include/eventbus/EventBus.h
)
ADD_LIBRARY(Dexode::EventBus ALIAS EventBus)

BIN
EventBusDiagram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

150
README.md
View File

@ -1,8 +1,156 @@
# EventBus
Simple and very fast event bus
Simple and very fast event bus.
The EventBus library is a convenient realization of the observer pattern.
It works perfectly to supplement the implementation of MVC logic (model-view-controller) in event-driven UIs
![EventBus Diagram](EventBusDiagram.png)
EventBus was created because I want something easy to use and faster than [CCNotificationCenter](https://github.com/cocos2d/cocos2d-x/blob/v2/cocos2dx/support/CCNotificationCenter.h)
from [cocos2d-x](https://github.com/cocos2d/cocos2d-x) library. Of course C++11 support was mandatory.
EventBus is:
- Fast
- Easy to use
- Strong typed
- Free
- Decouples notification senders and receivers
# Usage
Notify by Event object
```cpp
Dexode::EventBus bus;
Dexode::Event<int> simpleEvent{"simple"};
//...
bus.notify(simpleEvent, 2);//Everyone who listens will receive this notification.
```
Notify without Event object
```cpp
Dexode::EventBus bus;
//...
bus.notify<int>("simple", 2);//Everyone who listens will receive this notification.
```
Lambda listener
```cpp
Dexode::EventBus bus;
//...
int token = bus.listen<int>("simple", [](int value) // register listener
{
});
//If we want unlisten exact listener we can use token for it
bus.unlistenAll(token);
```
Listener is identified by `token`. Token is returned from EventBus::listen methods.
We can register multiple listeners on one token.
```cpp
Dexode::EventBus bus;
Dexode::Event<int> event{"simple"};
//...
int token = bus.listen(event, [](int value) // register listener
{
});
bus.listen(token, event, [](int value) // another listener
{
});
bus.unlistenAll(token);//Now those two lambdas will be removed from listeners
```
If you don't want handle manually with `token` you can use `EventCollector` class.
It is useful when we want have multiple listen in one class. So above example could look like this:
```cpp
Dexode::EventBus bus;
Dexode::Event<int> event{"simple"};
Dexode::EventCollector collector{&bus};
//...
collector.listen(event, [](int value) // register listener
{
});
collector.listen(event, [](int value) // another listener
{
});
collector.unlistenAll();//Now those two lambdas will be removed from listeners
```
```cpp
class Example
{
public:
Example(Dexode::EventBus& bus)
: _collector{&bus}
{
_collector.listen<int>("event1", std::bind(&Example::onEvent1, this, std::placeholders::_1));
_collector.listen<std::string>("event2", std::bind(&Example::onEvent2, this, std::placeholders::_1));
}
void onEvent1(int value)
{
}
void onEvent2(std::string value)
{
}
private:
Dexode::EventCollector _collector;// use RAII
};
//EventCollector sample
Dexode::EventBus bus;
Example ex{bus};
//...
bus.notify<int>("event1", 2);
```
# Add to your project
EventBus can be added as `ADD_SUBDIRECTORY` to your cmake file.
Then simply link it via `TARGET_LINK_LIBRARIES`
Example:
```
ADD_SUBDIRECTORY(lib/EventBus)
ADD_EXECUTABLE(MyExecutable
main.cpp
)
SET_TARGET_PROPERTIES(MyExecutable PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED YES
)
TARGET_LINK_LIBRARIES(MyExecutable PUBLIC Dexode::EventBus)
```
Also if you want you can install library and add it any other way you want.
# Performance
I have prepared some performance results. You can read about them [here](performance/README.md)
Small example:
```
check10NotificationsFor1kListeners 273 ns 273 ns 2609987 sum=-1.81219G
check10NotificationsFor1kListeners_EventBus2 267 ns 267 ns 2652159 sum=-1.77676G
check10NotificationsFor1kListeners_CCNotificationCenter 11172 ns 11171 ns 62865 sum=54.023M
```
# Thanks to
- [stanislawkabacinski](https://github.com/stanislawkabacinski) for fixing windows ;) [53d5026](https://github.com/gelldur/EventBus/commit/53d5026cad24810e82cd8d4a43d58cbfe329c502)
- [kuhar](https://github.com/kuhar) for his advice and suggestions for EventBus
- [ruslo](https://github.com/ruslo) for this great example: https://github.com/forexample/package-example
# License
EventBus source code can be used according to the Apache License, Version 2.0.
For more information see [LICENSE](LICENSE) file

View File

@ -7,32 +7,32 @@ namespace Dexode
{
template<typename ... Args>
class Notification2
class Event
{
public:
using Callback = std::function<void(Args...)>;
constexpr explicit Notification2(const std::string& name)
constexpr explicit Event(const std::string& name)
: _key{std::hash<std::string>{}(name + typeid(Callback).name())}
, _name{name}
{
}
constexpr Notification2(const Notification2& other)
constexpr Event(const Event& other)
: _key{other._key}
, _name{other._name}
{
}
Notification2(Notification2&& other)
Event(Event&& other)
: _key{other._key}
, _name{other._name}
{
}
Notification2& operator=(Notification2&&) = delete;
Event& operator=(Event&&) = delete;
Notification2& operator=(const Notification2&) = delete;
Event& operator=(const Event&) = delete;
const size_t getKey() const
{
@ -44,20 +44,20 @@ public:
return _name;
}
bool operator==(const Notification2& rhs) const
bool operator==(const Event& rhs) const
{
return _key == rhs._key &&
_name == rhs._name;
}
bool operator!=(const Notification2& rhs) const
bool operator!=(const Event& rhs) const
{
return !(rhs == *this);
}
friend std::ostream& operator<<(std::ostream& stream, const Notification2& notification)
friend std::ostream& operator<<(std::ostream& stream, const Event& notification)
{
stream << "Notification{name: " << notification._name << " key: " << notification._key;
stream << "Event{name: " << notification._name << " key: " << notification._key;
return stream;
}
@ -66,11 +66,11 @@ private:
const std::string _name;
};
template<typename NotificationType>
struct notification_traits;
template<typename EventType>
struct event_traits;
template<typename ... Args>
struct notification_traits<Notification2<Args...>>
struct event_traits<Event<Args...>>
{
using callback_type = typename std::function<void(Args...)>;
};

View File

@ -5,8 +5,9 @@
#include <map>
#include <memory>
#include <vector>
#include <cassert>
#include "Notification2.h"
#include "Event.h"
#if __cplusplus < 201402L
#error This library needs at least a C++14 compliant compiler
@ -15,17 +16,12 @@
namespace Dexode
{
namespace
{
template<typename T>
struct eventbus_traits
{
typedef T type;
};
}
class EventBus
{
public:
@ -45,41 +41,41 @@ public:
/**
* Register listener for notification. Returns token used for unlisten
*
* @param notification
* @param event
* @param callback - your callback to handle notification
* @return token used for unlisten
*/
template<typename ... Args>
int listen(const Notification2<Args...>& notification
int listen(const Event<Args...>& event
, typename eventbus_traits<const std::function<void(Args...)>&>::type callback)
{
const int token = ++_tokener;
listen(token, notification, callback);
listen(token, event, callback);
return token;
}
/**
* Register listener for notification. Returns token used for unlisten
*
* @param notification - name of your notification
* @param eventName - name of your event
* @param callback - your callback to handle notification
* @return token used for unlisten
*/
template<typename ... Args>
int listen(const std::string& notificationName
int listen(const std::string& eventName
, typename eventbus_traits<const std::function<void(Args...)>&>::type callback)
{
return listen(Dexode::Notification2<Args...>{notificationName}, callback);
return listen(Dexode::Event<Args...>{eventName}, callback);
}
/**
* @param token - unique token for identification receiver. Simply pass token from @see EventBus::listen
* @param notification - pass notification like "getNotificationXYZ()"
* @param event - pass notification like "getNotificationXYZ()"
* @param callback - your callback to handle notification
*/
template<typename ... Args>
void listen(const int token
, const Notification2<Args...>& notification
, const Event<Args...>& event
, typename eventbus_traits<const std::function<void(Args...)>&>::type callback)
{
using CallbackType = std::function<void(Args...)>;
@ -87,7 +83,7 @@ public:
assert(callback && "Please set it");//Check for valid object
std::unique_ptr<VectorInterface>& vector = _callbacks[notification.getKey()];
std::unique_ptr<VectorInterface>& vector = _callbacks[event.getKey()];
if (vector == nullptr)
{
vector.reset(new Vector{});
@ -111,25 +107,25 @@ public:
/**
* @param token - token from EventBus::listen
* @param notification - notification you wan't to unlisten. @see Notiier::listen
* @param event - notification you wan't to unlisten. @see Notiier::listen
*/
template<typename NotificationType, typename ... Args>
void unlisten(const int token, const NotificationType& notification)
template<typename EventType, typename ... Args>
void unlisten(const int token, const EventType& event)
{
auto found = _callbacks.find(notification.getKey());
auto found = _callbacks.find(event.getKey());
if (found != _callbacks.end())
{
found.second->remove(token);
}
}
template<typename NotificationType, typename ... Args>
void notify(const NotificationType& notification, Args&& ... params)
template<typename EventType, typename ... Args>
void notify(const EventType& event, Args&& ... params)
{
using CallbackType = typename notification_traits<NotificationType>::callback_type;
using CallbackType = typename event_traits<EventType>::callback_type;
using Vector = VectorImpl<CallbackType>;
auto found = _callbacks.find(notification.getKey());
auto found = _callbacks.find(event.getKey());
if (found == _callbacks.end())
{
return;// no such notifications
@ -148,12 +144,12 @@ public:
// We need to call this in form like: notify<int>("yes",value)
// We can't reduce it to notify("yes",value)
// It wouldn't be obvious which to call Notification<int> or Notification<int&>
// It wouldn't be obvious which to call Event<int> or Event<int&>
// So it can take to a lot of mistakes
template<typename ... Args>
void notify(const std::string& notificationName, Args&& ... params)
void notify(const std::string& eventName, Args&& ... params)
{
notify(Dexode::Notification2<Args...>{notificationName}, std::forward<Args>(params)...);
notify(Dexode::Event<Args...>{eventName}, std::forward<Args>(params)...);
}
private:

View File

@ -6,7 +6,7 @@
#include <memory>
#include "Notifier.h"
#include "EventBus.h"
namespace Dexode
{
@ -14,8 +14,8 @@ namespace Dexode
class EventCollector
{
public:
EventCollector(const std::shared_ptr<Notifier>& notifier);
EventCollector(Notifier& notifier = Notifier::getGlobal());
EventCollector(const std::shared_ptr<EventBus>& notifier);
EventCollector(EventBus* notifier);
EventCollector(EventCollector const& other);
EventCollector(EventCollector&& other);
@ -25,16 +25,16 @@ public:
EventCollector& operator=(EventCollector&& other);
/**
* Register listener for notification. Returns token used to unregister
* Register listener for notification.
*
* @param notification - pass notification like "getNotificationXYZ()"
* @param callback - your callback to handle notification
*/
template<typename ... Args>
void listen(const Notification<Args...>& notification
, typename notifier_traits<const std::function<void(Args...)>&>::type callback)
void listen(const Event<Args...>& notification
, typename eventbus_traits<const std::function<void(Args...)>&>::type callback)
{
if (!callback)
if (!callback || !_notifier)
{
return;//Skip such things
}
@ -48,6 +48,20 @@ public:
}
}
/**
* Register listener for notification. Returns token used for unlisten
*
* @param notification - name of your notification
* @param callback - your callback to handle notification
* @return token used for unlisten
*/
template<typename ... Args>
void listen(const std::string& notificationName
, typename eventbus_traits<const std::function<void(Args...)>&>::type callback)
{
listen(Dexode::Event<Args...>{notificationName}, callback);
}
void unlistenAll();
/**
@ -56,12 +70,15 @@ public:
template<typename NotificationType, typename ... Args>
void unlisten(const NotificationType& notification)
{
_notifier->unlisten(_token, notification);
if (_notifier)
{
_notifier->unlisten(_token, notification);
}
}
private:
int _token = 0;
std::shared_ptr<Notifier> _notifier;
std::shared_ptr<EventBus> _notifier;
};
}

View File

@ -74,7 +74,7 @@ check1kNotificationsFor1kListeners_CCNotificationCenter 9711 ns
-----------------------------------------------------------------------------------------------------------------------
checkNotifyFor10kListenersWhenNoOneListens 2 ns 2 ns 399367972 sum=0
checkNotifyFor10kListenersWhenNoOneListens_EventBus2 2 ns 2 ns 400616370 sum=0
checkNotifyFor10kListenersWhenNoOneListens_CCNotificationCenter 125173 ns 125162 ns 5657 sum=0```
checkNotifyFor10kListenersWhenNoOneListens_CCNotificationCenter 125173 ns 125162 ns 5657 sum=0
-----------------------------------------------------------------------------------------------------------------------
checkSimpleNotification 7 ns 7 ns 100833112 sum=384.648M
checkSimpleNotification_EventBus2 5 ns 5 ns 144959897 sum=552.978M

View File

@ -16,7 +16,7 @@ void checkNListeners(benchmark::State& state, const int listenersCount)
Dexode::EventBus bus;
int sum = 0;
Dexode::Notification2<int> simpleNotification("simple");
Dexode::Event<int> simpleNotification("simple");
for (int i = 0; i < listenersCount; ++i)
{
bus.listen(simpleNotification, [&](int value)
@ -82,7 +82,7 @@ void checkNNotificationsForNListeners(benchmark::State& state, const int notific
std::uniform_int_distribution<int> uniformDistribution(0, notificationsCount - 1);
//We generate here N different notifications
std::vector<Dexode::Notification2<int>> notifications;
std::vector<Dexode::Event<int>> notifications;
notifications.reserve(notificationsCount);
for (int i = 0; i < notificationsCount; ++i)
{
@ -132,8 +132,8 @@ void check100NotificationsFor10kListeners_EventBus2(benchmark::State& state)
void checkNotifyFor10kListenersWhenNoOneListens_EventBus2(benchmark::State& state)
{
Dexode::EventBus bus;
Dexode::Notification2<int> simpleNotification("simple");
Dexode::Notification2<int> unknownNotification("unknown");
Dexode::Event<int> simpleNotification("simple");
Dexode::Event<int> unknownNotification("unknown");
int sum = 0;
for (int i = 0; i < 10000; ++i)
{

View File

@ -4,10 +4,12 @@
#include <eventbus/EventCollector.h>
#include <cassert>
namespace
{
void null_deleter(Dexode::Notifier*)
void null_deleter(Dexode::EventBus*)
{
}
@ -16,17 +18,16 @@ void null_deleter(Dexode::Notifier*)
namespace Dexode
{
EventCollector::EventCollector(const std::shared_ptr<Notifier>& notifier)
EventCollector::EventCollector(const std::shared_ptr<EventBus>& notifier)
: _notifier(notifier)
{
assert(_notifier);
}
//Maybe ugly but hey ;) Less code and simply i can :D
EventCollector::EventCollector(Notifier& notifier)
: _notifier(&notifier, &null_deleter)
EventCollector::EventCollector(EventBus* notifier)
: _notifier(notifier, &null_deleter)
{
assert(_notifier);
}
EventCollector::EventCollector(EventCollector const& other)
@ -79,7 +80,7 @@ EventCollector& EventCollector::operator=(EventCollector&& other)
void EventCollector::unlistenAll()
{
if (_token != 0)
if (_token != 0 && _notifier)
{
_notifier->unlistenAll(_token);
}

View File

@ -4,7 +4,9 @@
ADD_EXECUTABLE(EventBusTest
eventbus/EventCollectorTest.cpp
eventbus/NotifierTest.cpp
eventbus/NotificationTest.cpp)
eventbus/NotificationTest.cpp
eventbus/sample.cpp
)
SET_TARGET_PROPERTIES(EventBusTest PROPERTIES
CXX_STANDARD 14

View File

@ -6,65 +6,57 @@
#include <eventbus/EventCollector.h>
namespace
{
MAKE_NOTIFICATION(SimpleNotification, int);
MAKE_NOTIFICATION(RefNotification, int &);
}
TEST_CASE("eventbus/EventCollector sample", "Simple test for EventCollector")
{
Dexode::Notifier bus;
Dexode::EventBus bus;
int callCount = 0;
{
Dexode::EventCollector listener{bus};
listener.listen(getNotificationSimpleNotification(), [&](int value)
Dexode::EventCollector listener{&bus};
listener.listen<int>("simple", [&](int value)
{
REQUIRE(value == 3);
++callCount;
});
bus.notify(getNotificationSimpleNotification(), 3);
bus.notify<int>("simple", 3);
REQUIRE(callCount == 1);
}
bus.notify(getNotificationSimpleNotification(), 2);
bus.notify<int>("simple", 2);
REQUIRE(callCount == 1);
}
TEST_CASE("eventbus/EventCollector unlistenAll", "EventCollector::unlistenAll")
{
Dexode::Notifier bus;
Dexode::EventCollector listener{bus};
Dexode::EventBus bus;
Dexode::EventCollector listener{&bus};
int callCount = 0;
listener.listen(getNotificationSimpleNotification(), [&](int value)
listener.listen<int>("simple", [&](int value)
{
REQUIRE(value == 3);
++callCount;
});
bus.notify(getNotificationSimpleNotification(), 3);
bus.notify<int>("simple", 3);
listener.unlistenAll();
bus.notify(getNotificationSimpleNotification(), 2);
bus.notify<int>("simple", 2);
REQUIRE(callCount == 1);
}
TEST_CASE("eventbus/EventCollector reset", "EventCollector reset when we reasign")
{
Dexode::Notifier bus;
Dexode::EventBus bus;
int callCount = 0;
Dexode::EventCollector listener{bus};
listener.listen(getNotificationSimpleNotification(), [&](int value)
Dexode::EventCollector listener{&bus};
Dexode::Event<int> simple{"simple"};
listener.listen(simple, [&](int value)
{
REQUIRE(value == 3);
++callCount;
});
bus.notify(getNotificationSimpleNotification(), 3);
bus.notify(simple, 3);
REQUIRE(callCount == 1);
listener = {};
listener = {nullptr};
bus.notify(getNotificationSimpleNotification(), 2);
bus.notify(simple, 2);
REQUIRE(callCount == 1);
}

View File

@ -3,49 +3,49 @@
//
#include <catch.hpp>
#include <eventbus/Notification2.h>
#include <eventbus/Event.h>
TEST_CASE("eventbus/Notification same", "Notifications should be same")
TEST_CASE("eventbus/Event same", "Notifications should be same")
{
{
Dexode::Notification2<int> one("one");
Dexode::Notification2<int> two("one");
Dexode::Event<int> one("one");
Dexode::Event<int> two("one");
REQUIRE(one == two);
}
{
Dexode::Notification2<int> one("one");
Dexode::Notification2<signed> two("one");
Dexode::Event<int> one("one");
Dexode::Event<signed> two("one");
REQUIRE(one == two);//int == signed
}
}
TEST_CASE("eventbus/Notification not same", "Notifications should different")
TEST_CASE("eventbus/Event not same", "Notifications should different")
{
{
Dexode::Notification2<int> one("one");
Dexode::Notification2<int> two("two");
Dexode::Event<int> one("one");
Dexode::Event<int> two("two");
REQUIRE(one != two);
}
{
Dexode::Notification2<int> one("one");
Dexode::Notification2<int&> two("two");
Dexode::Event<int> one("one");
Dexode::Event<int&> two("two");
//REQUIRE(one != two); //Different types!
}
{
Dexode::Notification2<unsigned> one("one");
Dexode::Notification2<signed> two("one");
Dexode::Event<unsigned> one("one");
Dexode::Event<signed> two("one");
//REQUIRE(one != two); //Different types!
}
{
Dexode::Notification2<int, int> one("one");
Dexode::Notification2<int, unsigned> two("one");
Dexode::Event<int, int> one("one");
Dexode::Event<int, unsigned> two("one");
//REQUIRE(one != two); //Different types!
}
}
TEST_CASE("eventbus/Notification should copy constructable", "Notifications should be copy constructable")
TEST_CASE("eventbus/Event should copy constructable", "Notifications should be copy constructable")
{
Dexode::Notification2<int> one("one");
Dexode::Notification2<int> two = one;
Dexode::Event<int> one("one");
Dexode::Event<int> two = one;
REQUIRE(one == two);
}

View File

@ -10,7 +10,7 @@
TEST_CASE("eventbus/Simple test", "Simple test")
{
Dexode::EventBus bus;
Dexode::Notification2<int> simpleNotification{"simple"};
Dexode::Event<int> simpleNotification{"simple"};
const auto token = bus.listen(simpleNotification, [](int value)
{
@ -31,8 +31,8 @@ TEST_CASE("eventbus/Simple test", "Simple test")
TEST_CASE("eventbus/Multiple listen on same token", "Listening on the same token")
{
Dexode::EventBus bus;
Dexode::Notification2<int> simpleNotification{"simple"};
Dexode::Notification2<int&> simpleRefNotification{"simple"};
Dexode::Event<int> simpleNotification{"simple"};
Dexode::Event<int&> simpleRefNotification{"simple"};
const auto token = bus.listen(simpleRefNotification, [](int& value)
{
REQUIRE(value == 3);
@ -63,7 +63,7 @@ TEST_CASE("eventbus/EventBus listen", "Listen without notification object. Using
REQUIRE(value == 3);
});
Dexode::Notification2<int> simpleNotification{"simple"};
Dexode::Event<int> simpleNotification{"simple"};
REQUIRE(isCalled == 0);
bus.notify(simpleNotification, 3);
REQUIRE(isCalled == 1);
@ -104,3 +104,44 @@ TEST_CASE("eventbus/EventBus listen & notify", "Listen & notify without notifica
bus.notify<int>("simple", 1);
REQUIRE(isCalled == 2);
}
TEST_CASE("eventbus/EventBus type conversion", "Check for type conversion")
{
class Example
{
public:
Example(Dexode::EventBus& bus)
{
Dexode::Event<int> event{"event1"};
_token = bus.listen(event, std::bind(&Example::onEvent1, this, std::placeholders::_1));
bus.listen(_token, event, std::bind(&Example::onEvent2, this, std::placeholders::_1));
}
int calledEvent1 = 0;
void onEvent1(int value)
{
++calledEvent1;
}
int calledEvent2 = 0;
void onEvent2(bool value)
{
++calledEvent2;
}
private:
int _token;
};
//EventCollector sample
Dexode::EventBus bus;
Example ex{bus};
REQUIRE(ex.calledEvent1 == 0);
REQUIRE(ex.calledEvent2 == 0);
bus.notify<int>("event1", 2);
REQUIRE(ex.calledEvent1 == 1);
REQUIRE(ex.calledEvent2 == 0);
}

104
test/eventbus/sample.cpp Normal file
View File

@ -0,0 +1,104 @@
//
// Created by Dawid Drozd aka Gelldur on 06.08.17.
//
#include <eventbus/EventBus.h>
#include <eventbus/EventCollector.h>
void sampleUsages()
{
{
//Notify by Event object
Dexode::EventBus bus;
Dexode::Event<int> simpleEvent{"simple"};
//...
bus.notify(simpleEvent, 2);//Everyone who listens will receive this notification.
}
{
//Notify without Event object
Dexode::EventBus bus;
//...
bus.notify<int>("simple", 2);//Everyone who listens will receive this notification.
}
{
//Lambda listener
Dexode::EventBus bus;
//...
int token = bus.listen<int>("simple", [](int value) // register listener
{
});
//If we want unlisten exact listener we can use token for it
bus.unlistenAll(token);
}
{
//Unlisten everyone who is waiting for event X //TODO
Dexode::EventBus bus;
Dexode::Event<int> event{"simple"};
//...
int token = bus.listen(event, [](int value) // register listener
{
});
//If we want unlisten exact listener we can use token for it
}
{
//Listen on some token
Dexode::EventBus bus;
Dexode::Event<int> event{"simple"};
//...
int token = bus.listen(event, [](int value) // register listener
{
});
bus.listen(token, event, [](int value) // another listener
{
});
bus.unlistenAll(token);//Now those two lambdas will be removed from listeners
}
{
//EventCollector sample
Dexode::EventBus bus;
Dexode::Event<int> event{"simple"};
Dexode::EventCollector collector{&bus};
//...
collector.listen(event, [](int value) // register listener
{
});
collector.listen(event, [](int value) // another listener
{
});
collector.unlistenAll();//Now those two lambdas will be removed from listeners
}
{
class Example
{
public:
Example(Dexode::EventBus& bus)
: _collector{&bus}
{
_collector.listen<int>("event1", std::bind(&Example::onEvent1, this, std::placeholders::_1));
_collector.listen<std::string>("event2", std::bind(&Example::onEvent2, this, std::placeholders::_1));
}
void onEvent1(int value)
{
}
void onEvent2(std::string value)
{
}
private:
Dexode::EventCollector _collector;// use RAII
};
//EventCollector sample
Dexode::EventBus bus;
Example ex{bus};
//...
bus.notify<int>("event1", 2);
}
}