Storing and later calling member function of unknown class - c++

I am trying to create a threadpool that can run functions from unknown classes. I do not wish to have to create non-members as a proxy.
I have managed to create a working pool & workerthread class and a task structure, all of these are templates.
// ThreadPool.h
/* Threadpool creates N WorkerThreads (each worker has a ptr to the creating pool),
these block until a task is ready then call ThreadPool::doTask() */
template<class T>
struct Task {
Task() : func(0), inst(0) { }
Task(boost::function<void(T*)> function, T* instance) : func(0), inst(0) {
func = function;
inst = instance;
}
void operator()() {
Task::func(inst);
}
T* inst;
boost::function<void(T*)> func;
};
template<class T>
class ThreadPool {
template<class T> friend class WorkerThread;
public:
void addTask(Task<T> task) {
... // Some stuff
}
bool doTask() {
Task<T> task;
... // Gets a task from std::queue
// Check the task actually exists!
if(task.func && task.inst) {
// Do the task
(task)();
}
}
private:
std::queue<Task<T>> mTasks;
};
As is, this code works, providing I determine the class for ThreadPool and Task. But I want to be able to call members of unknown class types. I had considered a void ptr but I could not find a way to convert this to a valid instance ptr. I have also looked into boost::mem_fun but struggled to really get to grips with it.
I have briefly read about C++0x and from what I understand, it should make solving my problem easier but I would like to solve this before then, if at all possible.

Why use a T* at all, instead of just boost::function<void ()>?
That way you can use free functions as well as member functions, and you can simplify your code.
A task for a member on an instance of class X could be queued like this:
poll.add(boost::bind(&X::member, x_instance, other_arguments));
With no casts and no templates in your code.
Update:
Use boost::function instead of your Task class. You then just need to keep track of the instances and call them as appropriate. For example:
class TaskQueue {
std::deque<boost::function<void ()> > m_tasks;
public:
void add(boost::function<void ()> const& f) { m_tasks.push_back(f); }
bool has_task() const { return !m_tasks.empty(); }
void do_task() {
m_tasks.front()();
m_tasks.pop_front();
}
};
int example_enqueue(TaskQueue* tq) {
boost::shared_ptr<RandomClass> rc(new RandomClass);
tq->add(boost::bind(&RandomClass::method, rc, arg_1, arg_whatever));
}
Note that by combining this method with boost::shared_ptr, you get automatic destruction of your objects when the function goes out of scope, if it's the last reference. That makes life a lot easier.

A void* would work. You just have to do a strong reinterpret_cast. But I would not use this solution. Boost has a bunch of ways of creating functor objects: http://www.boost.org/doc/libs/1_46_1/doc/html/function.html

Related

Handling function pointer with covariant types uniformly (how to call callbacks with derived types?)

Suppose that I have a Task class:
class Task;
using FinishedCallback = void (Task &);
class Task {
public:
// this function is implemented by derived classes
// there are other virtual functions too
virtual bool isFinished() = 0;
private:
std::vector<FinishedCallback> m_callbacks;
protected:
// these functions are called by derived classes
void addFinishedCallback(FinishedCallback callback) {
m_callbacks.push_back(callback);
}
void callFinishedCallbacks();
};
This class is the base class. I'd like to put as much implementation as possible into it. It has a m_callbacks vector, which stores the callbacks which are needed to be called when the task is finished (callFinishedCallbacks() does this).
Now, derive from this class:
class MyTask;
using MyFinishedCallback = void (MyTask &);
class MyTask: public Task {
public:
void addFinishedCallback(MyFinishedCallback callback) {
Task::addFinishedCallback(reinterpret_cast<FinishedCallback &>(callback));
}
// when MyTask finishes, it calls callFinishedCallbacks
};
Here, the finished callback has MyTask & parameter, so I have to reinterpret_cast it. So my program has UB. (The reason of the MyTask & type is that I don't have to cast Task & to MyTask & in the callback - it is for convenience).
But, even my program has UB, it works (the only real problem I could have if MyTask had multiple inheritance). Is it possible to modify this program to remove UB, while retaining its main attributes:
(compiled) code is small
small amount of coding work needed, if one derives from Task
no wrappers needed for callbacks
One idea would be to make a slight change to how you write your callbacks.
Use Task * rather than Task & as the callback parameter type.
At the beginning of the callback, use dynamic_cast to turn the Task * into a pointer to the derived type (MyType *).
void MyCallback(Task *task) {
auto *mytask = dynamic_cast<MyTask *>(task);
assert(mytask != nullptr);
// use mytask from here on
}
Another idea would be to use the Curiously Recurring Template Pattern (CRTP).
class BasicTask {
public:
virtual ~BasicTask() = default;
virtual bool isFinished() = 0;
};
template <typename Self>
class Task : public BasicTask {
private:
typedef void FinishedCallback(Self &task);
std::vector<FinishedCallback> m_callbacks;
protected:
void addFinishedCallback(FinishedCallback callback) {
m_callbacks.push_back(callback);
}
void callFinishedCallbacks();
};
Then you'd derive your specific task types from Task like this:
class MyTask : public Task<MyTask> { ... };
This reduced the amount of code you have to write (because there's only one source code implementation of addFinishedCallback), but it runs the risk of generating more object code. The optimizer and linker might be able to reign in that possibility.

how to create guard similar to boost::lock_guard

I want to create a guard, which locks a function on construction and unlocks it on destruction, e.g. calling the function with false and true.
class A {
void enable( bool flag );
};
within another method, I want to use:
A::anotherMethod( ... ) {
block_guard(A::enable); // now A::enable(false)
// some operation
} // now A::enable(true)
my ideas:
using template
template < class T >
class block_guard {
T t_;
public:
block_guard( T& t ) : t_(t) {
t_(false);
}
~block_guard() {
t_(true);
}
};
the question is, how to instantiate the template? maybe with boost::bind?
using boost::function
class block_guard {
typedef boost::function< void (bool) > T;
T t_;
public:
block_guard( T& t ) : t_(t) {
t_(false);
}
~block_guard() {
t_(true);
}
};
this works fine, but the call seems to be very complicated with
block_guard bg(boost::function< void (bool) >(boost::bind(&A::enable, pointer-to-A, _1));
any ideas?
maybe there is another, much simpler way?
First, realize that the member function is not all you need; you also need the object to invoke it on. There is no way in C++ for an object created in a function to implicitly capture the current this pointer.
I'm going to assume you don't have C++11 available. If you do, using your second solution with a lambda expression is easiest.
Now, if you don't care about the slight performance hit of boost::function (and you shouldn't), the second solution is good, but I would modify it slightly to make it more convenient to use by pulling the bind into the constructor.
class block_guard {
typedef boost::function< void (bool) > block_fn;
block_fn block_fn_;
public:
// For non-member functions and function objects:
template <typename Fn>
block_guard(Fn fn) : block_fn_(fn) {
block_fn_(false);
}
// For member functions:
template <typename T, typename Ret>
block_guard(T* obj, Ret (T::*fn)(bool)) : block_fn_(boost::bind(fn, obj, _1)) {
block_fn_(false);
}
~block_guard() {
block_fn_(true);
}
};
Usage:
block_guard guard(this, &A::enable);
I use a Ret parameter here because there's no reason not to allow functions that return something - the return value will simply get ignored.
If you don't want boost::function, the thing will get less easy to use, because you have to template the block guard. It becomes useful to make a block_guard specifically for member functions then. You also lose the ability to use non-void functions.
template <typename T>
class block_guard {
typedef void (T::*block_fn)(bool);
T* obj_;
block_fn block_fn_;
public:
block_guard(T* obj, block_fn fn) : obj_(obj), block_fn_(fn) {
(obj_->*block_fn_)(false);
}
~block_guard() {
(obj_->*block_fn_)(true);
}
};
Usage:
block_guard<A> guard(this, &A::enable);
Yes, there is a much simpler way, forget templates, generic thing and whatever not necessary and focus on the task.
All you need is a class with a ctor and a dtor. Write the dtor first, it reveals what you will need to work. Then write the ctor, taking arguments as needed. Lastly make the unwanted functions deleted (cctor, op=). Done.
Not generic, but straight to the point.

C++ design help for templated virtual function

I'm trying to implement a number of classes based on a a common class that abstracts a thread-pool using boost.threadpool. I've got something that works (in Xcode on osx 10.7.2) but I'm really not sure its good design or if its even safe (largely because of what I've read on-line about the use of virtual member functions with templates). I'm looking for some style advice on the best way to implement something like this. I'm learning as I go along here so I know a lot of this will be 'bad form'...
I have a base class called 'workqueue' like this:
template <typename T>
class Workqueue{
private:
pool *pThreadPool;
public:
Workqueue (int);
void Start (T);
void Schedule (T);
virtual bool Process(T) {return true;}
};
template <typename T> Workqueue<T>::Workqueue(int thread_count){
pThreadPool = new pool(thread_count);
}
template <typename T> void Workqueue<T>::Start(T data){
pThreadPool->schedule(boost::bind(&Workqueue::Process,this, data));
pThreadPool->wait();
}
template <typename T> void Workqueue<T>::Schedule(T data){
pThreadPool->schedule(boost::bind(&Workqueue::Process,this, data));
}
I then define a new service based on this class like this:
struct Service1Data{
string item_data;
};
class MyService : public Workqueue<Service1Data> {
public:
MyService (int);
bool Process (Service1Data);
};
MyService::MyService(int workers) : Workqueue<Service1Data>(workers) {}
bool MyService::Process(Service1Data service_data){
cout << "in process (" << service_data.item_data << ")" << endl;
return true;
}
(I've removed as much of the code to keep it simple so as shown would run forever as it continually submits new work). I use the service like this:
MyService *service1 = new MyService(5);
Service1Data x;
x.item_data = "testing";
service1->Start(x);
// will wait until no more work.
delete service1;
so my specific questions:
firstly (and please be gentle...) is this bad form and is there a much better way to do this? (and why?)
secondly - is this even safe given the virtual/template issues? I read somewhere that it should be safe if the class itself is templated and I think I understand the basic vtable issues - but really not sure of the specifics.
thirdly - the base workqueue class needs to have the member definitions in the 'h' file with the class definition for it to link. Not sure why that would be - I imagine it's a linker issue to do with the virtual/template issues and so makes me nervous.
all help gratefully received..
Chris
I think, you shouldn't mix processing of data with processing of queue.
I mean, you shouldn't have Process method in your Workqueue. Data may process itself, or your queue can get processing function as (template?) parameter.
Then you get rid of all your problems with virtual function. YourService class then should agregate Workqueue and may provide process function.
Also, I doubt if you really need Workqueue. You can just use pThreadPool in YourService.
If you need a common interface for services, you should specify it explicitly & separately. Your inheritance chain looks unclear. inheritance means is. Why YourService is Workqueue. I do not believe! I think YourService can use any sort of queue. But usage is aggregation.
EDIT:
Code will look like this:
template<typename Processor>
class WorkQueue
{
public:
WorkQueue(int count, Processor& processor):_processor(processor),_pool(count) {}
template <typename Data>
void schedule(const Data& data)
{
_pool->schedule(std::bind(&Processor::process,_processor, data));
}
template <typename Data>
void run(const Data& data)
{
schedule(data);
_pool->wait();
}
private:
Processor& _processor;
pool _pool;
};
class Service
{
public:
virtual void run() = 0;
virtual ~Service() {}
};
struct ServiceParams
{
int param;
};
class MyService: public Service
{
friend class WorkQueue<MyService>;
public:
MyService(const ServiceParams& params): _params(params), _queue(1, *this) {}
void run() { return _queue.run(_params); }
private:
ServiceParams _params;
WorkQueue<MyService> _queue;
void process(const ServiceParams& params) {std::cout <<"hello, world\n";}
};
EDIT: I originally considered usage as:
ServiceData data;
Service* service = new MyService(data);
service->run();
delete service;
Little things I can obviously point out:
overuse of new and delete when you could create automatic objects.
For example, if your work-queue and the pool have the same lifetime then:
template <typename T> class Workqueue
{
private:
pool threadPool;
// // etc
};
template< typename T >
Workqueue::Workqueue( int numThreads ) : threadPool( numThreads )
{
}
Your base class needs a virtual destructor, and as it stands Start could call Schedule rather than implement the same line of code (with the boost::bind) twice. Ideally the constructor that takes an int member only will be declared explicit.
You probably need logic to wait for threads to complete.
I think a good design should isolate the queuing and work/task separately. In your design, both are tightly coupled. This design is good if you want to create separate pool for every type of work/task.
Another approach is to create a separate Work class containing the process function. Then your MyService will extend Work. And WorkQueue class will accept Work and by that means any derived class too. This approach is more generic in nature. So same worker queue can accept different type of work/task. Below code illustration will clear more.
Just to add this approach can also be used if you want to have different pool for different type of data. It is more flexible in nature.
template <typename T>
class Work{
T data; // contains the actual data to work on
public:
Work(T data) : data(data) {} // constructor to init data
virtual bool Process(T) {return false;} // returns false to tell process failed
T getData() { return data; } // get the data
};
class MyWork : public Work<Service1Data> {
public:
MyService (Service1Data data) :
Work(data) {}
bool Process (Service1Data); // Implement your work specific process func
};
bool MyWork::Process(Service1Data service_data){
cout << "in process (" << service_data.item_data << ")" << endl;
return true;
}
class Workqueue{
private:
pool *pThreadPool;
public:
Workqueue (int);
void Start (Work);
void Schedule (Work);
};
Workqueue::Workqueue(int thread_count){
pThreadPool = new pool(thread_count);
}
void Workqueue::Start(Work workToDo){
pThreadPool->schedule(boost::bind(&Work::Process,this, workToDo.getData()));
pThreadPool->wait();
}
void Workqueue::Schedule(Work data){
pThreadPool->schedule(boost::bind(&Work::Process,this, workToDo.getData()));
}
Usage
Service1Data x;
x.item_data = "testing";
MyWork myWork(x);
Workqueue wq = new Workqueue(5);
wq->Start(myWork);
// will wait until no more work.
delete service1;
Now to achieve different pools for different type of work/task, create two Workqueue with different pool size and then give one only one type of work and other another type of work.
NOTE: Above code might contain syntax errors, it just there to convey the design. Treat it as pseudo code.

Storing and Executing Functions From A Class (C++)

I have a class called "Tasks" that needs to store methods from other classes, and be able to execute them. I'd like it to work like this:
Window *window = new Window();
Tasks* tasks = new Tasks();
tasks.m_tasks.Add(window.Create("My Window"));
Then I could call that window creation from my tasks class, by iterating over the stored tasks and executing each one:
tasks.ExecuteTasks();
What would be the datastructure of "m_tasks" that stores the functions, and how could I call them?
I would use a std::list<std::function<void()> >, or boost::function if std::function is not available.
And you'll need to change the syntax of that Add call to avoid executing the Create method right away.
C++11:
class Tasks {
public:
void Add(const std::function<void()>& f)
{ callbacks_.push_back( f ); }
void Add(std::function<void()>&& f)
{ callbacks_.emplace_back( std::move( f ) ); }
// ...
private:
std::list<std::function<void()> > callbacks_;
};
int main() {
Window window;
// ...
tasks.Add( [&]() { window.Create("My Window"); } );
// ...
}
C++03:
class Tasks {
public:
void Add(const boost::function<void()>& f)
{ callbacks_.push_back( f ); }
private:
std::list<boost::function<void()> > callbacks_;
};
int main() {
// ...
tasks.Add( boost::bind( &Window::Create, boost::ref(window), "My Window" ) );
// ...
}
You could use a list of tr1 or boost ::functions as #aschepler says, but this scenario is perfect for boost::signals.
class Tasks {
boost::signal<void ()> m_tasks;
};
// ...
tasks.m_tasks.connect(&someFunction);
// ExecuteTasks:
tasks.m_tasks();
This allows for a lot of extra functionality, like handling arguments, returns, and letting clients disconnect their tasks if they want to.
You'll need slightly complicated structure for this:
class Task
{
public:
virtual void Execute()=0;
};
template<class T, class R, class P1>
class Function1 : public Task
{
public:
Function1(T *ptr, R (T::*fptr)(P1), P1 p1) : ptr(ptr), fptr(fptr),p1(p1) { }
void Execute() { (ptr->*fptr)(p1); }
private:
T *ptr;
R (T::*fptr)(P1);
P1 p1;
};
std::vector<Task*> vec;
This is relatively straightforward if you know what the arguments will be. You could use a function pointer, with some extras to make it a 'method' pointer. See:
http://mdzahidh.wordpress.com/2008/07/16/pointer-to-c-class-methods-or-should-you-call-em-method-pointers/
However, this would not allow you to pass arbitrary arguments. You might be able to do it with C++ templates, but it would be nasty hackery. I would strongly advise avoiding this and going with traditional function/method pointers if at all possible.
m_tasks is going to be a collection of some sort, I'd probably use a list unless you need to be able to add/remove in the middle. The thing you will be storing in the list is a function pointer. That is, a pointer to a function. With the straightforward version of the code I have below, you cannot have generic function pointers, you must be specific about the parameter types and the return value type. It might be possible to use templates to break this restriction. I don't know off the top of my head.
// define FunctionPtr as a pointer to a function that takes a single char* param and returns void
typedef void(*FunctionPtr)(char*);
// define an stl:list of FunctionPtr items
std:list<FunctionPtr> m_tasks;

Event Callback Daemon

I am working on an event daemon in C++ that I would like to use member function callbacks. Basically an event queue would collect events which the daemon continuously services. There is a base class Event struct with an ID and all events would derive from it. I would like the methods registered for each event to use the derived event type in their signature.
struct Event
{
unsigned int eventId;
};
struct EventA : public Event
{
unsigned int x;
unsigned int y;
};
// and struct EventB, EventC (use your imagination...)
const unsigned int EVENT_A = 1;
const unsigned int EVENT_B = 2;
const unsigned int EVENT_C = 3;
class Foo
{
public:
void handlerMethod_A(const EventA& e);
void handlerMethod_B(const EventB& e);
};
class Bar
{
public:
void handlerMethod_C(const EventC& e);
};
Then the Daemon would allow these classes to subscribe their member functions using their 'this' pointer.
class EventDaemon
{
public:
void serviceEvents();
template <class CallbackClass, class EventType>
void subscribe(
const unsigned int eventId,
CallbackClass* classInstancePtr,
void (CallbackClass::*funcPtr)(EventType));
private:
Queue<Event*> eventQueue_;
};
So outside this class you could do something like:
EventDaemon* ed = new EventDaemon();
Foo* foo = new Foo();
Bar* bar = new Bar();
ed->subscribe(EVENT_A, foo, Foo::handlerMethod_A);
ed->subscribe(EVENT_B, foo, Foo::handlerMethod_B);
ed->subscribe(EVENT_C, bar, Bar::handlerMethod_C);
And the EventDaemon loop would be along the lines of
void EventDaemon::serviceEvents()
{
while (true)
{
if (eventQueue_.empty())
{
// yield to other threads
}
else
{
// pop an event out of the FIFO queue
Event e* = eventQueue_.pop();
// somehow look up the callback info and use it
classInstancePtr->*funcPtr(reinterpret_cast<?*>(e));
}
}
}
So my question is how I can store the 'this' pointers and member function pointers in some sort of array by event ID. That way I could look up the 'classInstancePtr' and 'funcPtr' by using e->eventId and the event type as well for the reinterpret cast.
You are working too hard. Use boost functions:
http://www.boost.org/doc/libs/1_47_0/doc/html/function.html
These work whether you have a object or not. They will increase your compile time.
Note, whenever you come across these types of questions where you know many people must have had the same problem, there is probably a simple option and, if it is not in the standard library, it is probably in boost.
In response to Nick, I'm constantly throwing boost function objects into vectors and whatnot.
I've found that, while boost function objects can hold object references, having them do so can lead to bugs with object lifetimes and it is better to have them hold copies of the class objects (you run into the same bugs however you try to hold a reference to a object instance that you don't necessarily control the lifetime of). The pattern:
class Foo
{
struct Member
{
// member variable definitions
};
shared_ptr<Member> m_; // the only real member variable
public:
// etc. including the all-important copy
// constructor and assignment operator and
// don't forget the member function that gets stuck into
// the boost function as a callback!
};
where all the member variables get held in a shared_ptr allows for good performance and you don't have to worry about lifetimes of objects held by function objects because you can copy them by value. Threaded code (what I always seem to be writing nowadays) needs additional things like at least one boost mutex element in Member or some other way to assure values don't get stomped on.
boost::function [or, if your system supports it, std::function] will take care of holding the this pointer quite well, with the added benefit of not requiring an actual object if it isn't necessary. So instead of void (SomeType::*)(EventA) you have std::function<void(EventA)>, and you call std::bind as appropriate.
subscribe(EVENT_A, std::bind(&foo::handleEventA, &foo, std::placeholders::_1));
A trivial wrapper function can be used to provide the same signature as you originally proposed and hide the nasty placeholders.
You do, of course, still have the issue of each event type having its own signature, and the need to ensure you use the correct Event ID code. In both cases, your base Event type can help out. Your callback need not accept an EventA&; it can accept an Event&, and dynamic_cast it to an EventA at runtime. For the ID, query the type directly.
struct Event {
virtual void ~Event() { }
virtual int ID() =0;
};
template<typename E>
struct EventHelper : Event {
virtual int ID() { return E::EventID; }
};
struct EventA : EventHelper<EventA> {
static const int EventID = 89;
};
Now, if you have an Event* object [when you go to dispatch your events], you can do p->ID() to get the appropriate ID, and if you have a EventA type [when you register your callbacks] you can do EventA::EventID.
So now, all you have to store is a std::function<void(const Event&)> and an associated int value for each of your callbacks, no matter what the actual type of event you have.
void subscribe(int id, std::function<void(const Event&)> f) {
callbacks.insert(std::make_pair(id, f));
}
template<typename E>
void subscribe(std::function<void(const Event&)> f) {
subscribe(E::EventID, f);
}
template<typename O, typename E>
void subscribe(O* p, void (O::*f)(const Event&)) {
subscribe<E>(std::bind(f, p, std::placeholders::_1));
}
You still have the issue that user error when subscribing can result in a function being called incorrectly. If you've used dynamic_cast correctly within the callback, this will get caught at runtime, but a compile time check would be nice. So what if we automate that dynamic_cast? For this step, I'm going to use c++11 lambdas, but it can be implemented in C++03 as well using a variety of methods.
template <class CallbackClass, class EventType>
void subscribe(CallbackClass* classInstancePtr, void (CallbackClass::*funcPtr)(EventType)) {
subscribe<EventType::EventID>([&](const Event& e) {
(classInstancePtr->*funcPtr)(dynamic_cast<const EventType&>(e));
});
}
So now we've gone full circle back to your original interface where your callbacks accept the actual type they are going to be working on, but internally you've squeezed them all into a common signature.
Okay, so I finished an implementation of my original desired interface. I was looking through Dennis' answer but eventually got lead to functors and I realized what I was looking for was a simple polymorphic solution. I failed to grasp before that I could create a non-templated base class with which to use for storing templated classes in vectors/arrays. I think this is what mheyman was trying to tell me... so I apologize I didn't get it right away. Just to clarify though I was really looking for the implementation solution for my own benefit and knowledge, not just a 3rd party library to get the job done. So I guess I would be looking for how Boost functions work, not just that they exist and are awesome.
If anyone is still interested here are the important parts of what I ended up with (minus some extraneous stuff and error checking):
EventFunctor is basically a pointer to member function template class
EventFunctorBase is the non-templated base class used to store them in a vector
The Event is dynamic cast using the templated type before being used to invoke the callback
class EventDaemon
{
public:
template <class CallbackClass, class EventType>
void subscribe(
const EventId eventId,
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&));
private:
EventFunctorBase* callbacks_[MAX_NUM_EVENTS];
};
template <class CallbackClass, class EventType>
void EventDaemon::subscribe(
const EventId eventId,
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&))
{
callbacks_[eventId] = new EventFunctor<CallbackClass,EventType>(callbackClassInstancePtr,funcPtr);
}
class EventFunctorBase
{
public:
EventFunctorBase();
virtual ~EventFunctorBase();
virtual void operator()(const Event& e)=0;
};
template <class CallbackClass, class EventType>
class EventFunctor : public EventFunctorBase
{
public:
EventFunctor(
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&));
virtual void operator()(const Event& e);
private:
CallbackClass* callbackClassInstancePtr_;
void (CallbackClass::*funcPtr_)(const EventType&);
};
template <class CallbackClass, class EventType>
EventFunctor<CallbackClass,EventType>::EventFunctor(
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&))
:
callbackClassInstancePtr_(callbackClassInstancePtr),
funcPtr_(funcPtr)
{
}
template <class CallbackClass, class EventType>
/*virtual*/ void EventFunctor<CallbackClass,EventType>::operator()(const Event& e)
{
(callbackClassInstancePtr_->*funcPtr_)(dynamic_cast<const EventType&>(e));
}
EventDaemon loop
while (true_)
{
if (eventQueue_->empty())
{
// yield to other threads
}
else
{
Event* e = eventQueue_.pop();
(*(callbacks_[e->ID]))(*e);
}
}
My final steps here will be to try and remove the need to have the developer define an ID for each event... of course this might end up a new post later this week.