mirror of
https://github.com/gelldur/EventBus.git
synced 2024-12-26 18:51: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