mirror of
https://github.com/gelldur/EventBus.git
synced 2024-12-27 12:21:02 +08:00
Init with first implementation
This commit is contained in:
parent
b0d3ea9ad0
commit
e40d1a3674
77
src/Notification.h
Normal file
77
src/Notification.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Dexode
|
||||||
|
{
|
||||||
|
|
||||||
|
enum NotificationConst
|
||||||
|
{
|
||||||
|
UNUSED_TAG = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
inline int getUniqueId()
|
||||||
|
{
|
||||||
|
static int id = NotificationConst::UNUSED_TAG + 1;
|
||||||
|
return ++id;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getToken()
|
||||||
|
{
|
||||||
|
return getUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
inline int getTokenForType()
|
||||||
|
{
|
||||||
|
static int id_for_type = getUniqueId();
|
||||||
|
return id_for_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ... Args>
|
||||||
|
class Notification
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Callback = std::function<void(Args...)>;
|
||||||
|
|
||||||
|
//dummyInt used only for prevent creating unused notifications you should use MAKE_NOTIFICATION
|
||||||
|
Notification(int dummyInt)
|
||||||
|
: tag(getUniqueId())
|
||||||
|
{
|
||||||
|
assert(dummyInt == 691283);
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification& operator=(const Notification&) = delete;
|
||||||
|
|
||||||
|
Notification& operator=(Notification&& notification)
|
||||||
|
{
|
||||||
|
tag = notification.tag;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification(const Notification& notification)
|
||||||
|
: tag(notification.tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification(Notification&& notification)
|
||||||
|
: tag(notification.tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int tag = NotificationConst::UNUSED_TAG;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename NotificationType>
|
||||||
|
struct notification_traits;
|
||||||
|
|
||||||
|
template<typename ... Args>
|
||||||
|
struct notification_traits<Notification<Args...>>
|
||||||
|
{
|
||||||
|
using callback_type = typename std::function<void(Args...)>;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAKE_NOTIFICATION(NAME, args...) inline const Dexode::Notification<args>& getNotification##NAME(){static const Dexode::Notification<args> variable(691283); return variable;}
|
||||||
|
|
||||||
|
}
|
149
src/Notifier.h
Normal file
149
src/Notifier.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Notification.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace Dexode
|
||||||
|
{
|
||||||
|
|
||||||
|
class Notifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Notifier()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Notifier()
|
||||||
|
{
|
||||||
|
for (auto&& it = _callbacks.begin(); it != _callbacks.end(); ++it)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Notifier& operator=(const Notifier&) = delete;
|
||||||
|
|
||||||
|
Notifier(const Notifier&) = delete;
|
||||||
|
|
||||||
|
Notifier& operator=(Notifier&&) = delete;
|
||||||
|
|
||||||
|
Notifier(Notifier&&) = delete;
|
||||||
|
|
||||||
|
static Notifier& getGlobal()
|
||||||
|
{
|
||||||
|
static Notifier globalNotifier;
|
||||||
|
return globalNotifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ... Args>
|
||||||
|
void listen(const int token
|
||||||
|
, const Notification<Args...>& notification
|
||||||
|
, const std::function<void(Args...)>& callback)
|
||||||
|
{
|
||||||
|
using CallbackType = std::function<void(Args...)>;
|
||||||
|
|
||||||
|
//Check for valid object
|
||||||
|
assert(callback && "Please set it");
|
||||||
|
|
||||||
|
if (_callbacks[notification.tag] == nullptr)
|
||||||
|
{
|
||||||
|
auto pVector = new VectorImpl<CallbackType>();
|
||||||
|
pVector->container.reserve(4);
|
||||||
|
|
||||||
|
_callbacks[notification.tag] = pVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pVector = static_cast<VectorImpl <CallbackType>*>(_callbacks[notification.tag]);
|
||||||
|
pVector->container.emplace_back(std::make_pair(callback, token));
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlistenAll(const int token)
|
||||||
|
{
|
||||||
|
for (auto&& element : _callbacks)
|
||||||
|
{
|
||||||
|
element.second->remove(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NotificationType, typename ... Args>
|
||||||
|
void unlisten(const int token, const NotificationType& notification)
|
||||||
|
{
|
||||||
|
using CallbackType = typename notification_traits<NotificationType>::callback_type;
|
||||||
|
assert(notification.tag > NotificationConst::UNUSED_TAG);
|
||||||
|
|
||||||
|
if (_callbacks[notification.tag] == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(dynamic_cast<VectorImpl <CallbackType>*>(_callbacks[notification.tag]) != nullptr);
|
||||||
|
_callbacks[notification.tag]->remove(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NotificationType, typename ... Args>
|
||||||
|
void notify(const NotificationType& notification, Args&& ... params)
|
||||||
|
{
|
||||||
|
using CallbackType = typename notification_traits<NotificationType>::callback_type;
|
||||||
|
assert(notification.tag > NotificationConst::UNUSED_TAG);
|
||||||
|
|
||||||
|
if (_callbacks[notification.tag] == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(dynamic_cast<VectorImpl <CallbackType>*>(_callbacks[notification.tag]) != nullptr);
|
||||||
|
|
||||||
|
//Copy? TODO think about it Use 2 vectors?
|
||||||
|
auto pVector = static_cast<VectorImpl <CallbackType>*>(_callbacks[notification.tag]);
|
||||||
|
for (auto&& element : pVector->container)
|
||||||
|
{
|
||||||
|
element.first(std::forward<Args>(params)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct VectorInterface
|
||||||
|
{
|
||||||
|
virtual ~VectorInterface()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void remove(const int token) = 0;
|
||||||
|
virtual void removeAll() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
struct VectorImpl : public VectorInterface
|
||||||
|
{
|
||||||
|
std::vector<std::pair<Type, int>> container;
|
||||||
|
|
||||||
|
virtual ~VectorImpl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void removeAll() override
|
||||||
|
{
|
||||||
|
container.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void remove(const int token) override
|
||||||
|
{
|
||||||
|
for (int i = container.size() - 1; i > -1; --i)
|
||||||
|
{
|
||||||
|
if (container[i].second == token)
|
||||||
|
{
|
||||||
|
std::swap(container[i], container.back());
|
||||||
|
container.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<int, VectorInterface*> _callbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace Dexode */
|
Loading…
x
Reference in New Issue
Block a user