Utility class to handle a set of listeners and their callbacks using variadic templates
#ifndef __LISTENERSET_H__ | |
#define __LISTENERSET_H__ | |
#include <set> | |
/* | |
Usage: | |
class IInputListener | |
{ | |
public: | |
virtual ~IInputListener() {} | |
virtual void keyDown(KeyCode code) = 0; | |
virtual void keyUp(KeyCode code) = 0; | |
}; | |
... | |
ListenerSet<IInputListener*> listeners; | |
... | |
listeners.addListener(new PlayerInputListener()); | |
listeners.addListener(new UserInterfaceInputListener()); | |
... | |
listeners.notify(&IInputListener::keyDown, keyCode); | |
listeners.notify(&IInputListener::keyUp, keyCode); | |
*/ | |
template <class Type> class ListenerSet | |
{ | |
public: | |
ListenerSet() {} | |
virtual ~ListenerSet() {} | |
inline void addListener(Type listener) | |
{ | |
if (m_notifying) | |
{ | |
m_pendingAddition.insert(listener); | |
m_pendingRemoval.erase(listener); | |
} | |
else | |
{ | |
m_listeners.insert(listener); | |
} | |
} | |
inline void removeListener(Type listener) | |
{ | |
if (m_notifying) | |
{ | |
m_pendingRemoval.insert(listener); | |
m_pendingAddition.erase(listener); | |
} | |
else | |
{ | |
m_listeners.erase(listener); | |
} | |
} | |
template <class Function, class... Arguments> | |
inline void notify(Function&& f, Arguments&&... args) | |
{ | |
m_notifying = true; | |
for (Type listener : m_listeners) | |
{ | |
auto callback = std::bind(f, listener, args...); | |
callback(listener); | |
} | |
m_notifying = false; | |
for (Type listener : m_pendingRemoval) | |
{ | |
m_listeners.erase(listener); | |
} | |
m_pendingRemoval.clear(); | |
for (Type listener : m_pendingAddition) | |
{ | |
m_listeners.insert(listener); | |
} | |
m_pendingAddition.clear(); | |
} | |
private: | |
bool m_notifying; | |
std::set<Type> m_pendingRemoval; | |
std::set<Type> m_pendingAddition; | |
std::set<Type> m_listeners; | |
}; | |
#endif // __LISTENERSET_H__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment