1

I have a simple thread pool implementation using boost::function, and boost::bind to reduce the member function signature to void func(void). This then uses a queue of boost::function and int pairs, pops the top of the queue, and executes the function (all wrapped in a mutex block).

threadPool->addJob(boost::bind(&Foo::bar, this, arg1, arg2));

...

typedef boost::function<void(void)> func;
std::queue<std::pair<func, int> > funcQ;

void ThreadPool::addJob(func f){
    funcQ.push(std::make_pair(f, j));
}

if (!funcQ.empty()){
    func localFunc = (funcQ.front()).first;
    ...
    funcQ.pop();
    ...
    localFunc();
}

However, after a few iterations, this was causing a segfault when I invoked the () operator on the function, so I tossed in an assert statement to make sure that the function was callable:

...
assert(funcQ.front().first);
func localFunc = (funcQ.front()).first;
...

Lo and behold, after a few iterations the assert trips, indicating that my boost::function was not callable.

I first thought that perhaps the function data (from the Foo class) had been destroyed before the function was called, however as I understand it, boost::function creates a copy of the data to form the closure anyhow. Unfortunately I don't know enough about what causes boost::functions to be invalid to progress any further on the problem. Am I binding the member function incorrectly, or does the problem lie somewhere between there and trying to call it?

Edit: I should have mentioned: Foo is allocated on the heap, and isn't deleted until the threads are joined.

Oxonium
  • 11
  • 3
  • 2
    `boost::function` will create a copy of the `this` pointer you pass it, i.e. it keeps a pointer with the same address. It does not own a copy of `*this`. – juanchopanza Jul 15 '13 at 12:19

1 Answers1

1

std::queue is not thread safe. When you say you are using mutex for popping from the queue, I understand you will be doing the same for pushing in the queue.

Also, you need to take care of the lifetime of Foo. Consider passing a shared_ptr to asynchronous functions. (shared_from_this() instead of this)

Note: You can use boost::asio to achieve task scheduling. Here is a very good article on that http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio/

aamir
  • 151
  • 6
  • I am indeed wrapping every time the queue is accessed in a mutex. Foo is allocated on the heap, and the destructor isn't called until the threads are joined. Also, I made this to try and understand how to use boost::function and boost::bind, but I will definitely look into boost::asio, thanks! – Oxonium Jul 15 '13 at 13:07