Storing and later calling member function of unknown class
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, pro开发者_如何学Cviding 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
精彩评论