Multithreading using the boost library

gagneet picture gagneet · Dec 5, 2008 · Viewed 10.5k times · Source

Wish to simultaneously call a function multiple times. I wish to use threads to call a function which will utilize the machines capability to the fullest. This is a 8 core machine, and my requirement is to use the machine cpu from 10% to 100% or more.

My requirement is to use the boost class. Is there any way I can accomplish this using the boost thread or threadpool library? Or some other way to do it?

Also, if I have to call multiple functions with different parameters each time (with separate threads), what is the best way to do this? [using boost or not using boost] and how?

#include <iostream>
#include <fstream>
#include <string.h>
#include <time.h>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>

using namespace std;
using boost::mutex;
using boost::thread;

int threadedAPI1( );
int threadedAPI2( );
int threadedAPI3( );
int threadedAPI4( );

int threadedAPI1( ) {
    cout << "Thread0" << endl;
}


int threadedAPI2( ) {
    cout << "Thread1" << endl;
}

int threadedAPI3( ) {
    cout << "Thread2" << endl;
}

int threadedAPI4( ) {
    cout << "Thread3" << endl;
}

int main(int argc, char* argv[]) {

    boost::threadpool::thread_pool<> threads(4);
    // start a new thread that calls the "threadLockedAPI" function
    threads.schedule(boost::bind(&threadedAPI1,0));
    threads.schedule(boost::bind(&threadedAPI2,1));
    threads.schedule(boost::bind(&threadedAPI3,2));
    threads.schedule(boost::bind(&threadedAPI4,3));
    // wait for the thread to finish
    threads.wait();

    return 0;
}

The above is not working and I am not sure why? :-(

Answer

jalf picture jalf · Dec 5, 2008

I suggest that you read up on the documentation for the functions you use. From your comment in James Hopkin's answer, it seems like you don't know what boost::bind does, but simply copy-pasted the code.

boost::bind takes a function (call it f), and optionally a number of parameters, and returns a function which, when called, calls f with the specified parameters.

That is, boost::bind(threadedAPI1, 0)() (creating a function which takes no arguments and calls threadedAPI1() with the argument 0, and then calling that) is equivalent to threadedAPI1(0).

Since your threadedAPI functions don't actually take any parameters, you can't pass any arguments to them. That is just fundamental C++. You can't call threadedAPI1(0), but only threadedAPI1(), and yet when you call the function, you try (via boost::bind) to pass the integer 0 as an argument.

So the simple answer to your question is to simply define threadedAPI1 as follows:

int threadedAPI1(int i);

However, one way to avoid the boost::bind calls is to call a functor instead of a free function when launching the thread. Declare a class something like this:

struct threadedAPI {
  threadedAPI(int i) : i(i) {} // A constructor taking the arguments you wish to pass to the thread, and saves them in the class instance.

  void operator()() { // The () operator is the function that is actually called when the thread starts, and because it is just a regular class member function, it can see the 'i' variable initialized by the constructor
    cout << "Thread" << i << endl; // No need to create 4 identical functions. We can just reuse this one, and pass a different `i` each time we call it.
  }
private:
  int i;
};

Finally, depending on what you need, plain threads may be better suited than a threadpool. In general, a thread pool only runs a limited number of threads, so it may queue up some tasks until one of its threads finish executing. It is mainly intended for cases where you have many short-lived tasks.

If you have a fixed number of longer-duration tasks, creating a dedicated thread for each may be the way to go.