Reputation: 978
I've written a simple subscriber event system taking advantage of std::function
. It works great! (and I can do some big enhancements later with thread-pooling for expensive callbacks)
The next step to improve this is to handle events/callbacks with more than one parameter.
Other than forcing struct
s/class
es or using std::tuple
s in the callback arguments (I want to keep the functions clean or use existing simple funcs). Is there a good way to do this, and have multiple template parameters all with the same code?
#pragma once
#include <mutex>
#include <vector>
template<typename PARAM>
class SoyEvent
{
public:
typedef std::function<void(PARAM&)> FUNCTION;
public:
// helper for member functions
template<class CLASS>
void AddListener(CLASS& This,void(CLASS::*Member)(PARAM&))
{
// http://stackoverflow.com/a/7582576
auto bound = std::bind( Member, &This, std::placeholders::_1 );
AddListener( bound );
}
template<class CLASS>
void RemoveListener(CLASS& This,FUNCTION Member)
{
RemoveListener( std::bind( &Member, &This ) );
}
// add static or lambda
void AddListener(FUNCTION Function)
{
std::lock_guard<std::mutex> lock(mListenerLock);
mListeners.push_back(Function);
}
void RemoveListener(FUNCTION Function)
{
std::lock_guard<std::mutex> lock(mListenerLock);
mListeners.erase(Function);
}
void OnTriggered(PARAM& Param)
{
std::lock_guard<std::mutex> lock(mListenerLock);
// todo: execute on seperate threads with a scheduler which can just execute std::functions
for ( auto it=mListeners.begin(); it!=mListeners.end(); it++ )
{
auto& Function = *it;
Function( Param );
}
}
private:
std::mutex mListenerLock;
std::vector<FUNCTION> mListeners;
};
Upvotes: 2
Views: 1203
Reputation: 5980
Why not just use variadic templates, i.e. change your class definition from:
template <typename PARAM>
class SoyEvent {
// Implementation
};
To something like:
template <typename... PARAMS>
class SoyEvent {
// Implementation
};
And then change your FUNCTION
typedef to:
typedef std::function<void(PARAMS&...)> FUNCTION;
And in general change all instances of PARAM&
to PARAMS&...
.
Upvotes: 3