Using boost::threadpool with boost::future

Here is a small c++ function which allows you to submit async jobs into the thread pool and track their execution status using the conception of futures:

#include "boost/threadpool.hpp"
#include "boost/future.hpp"
#include "boost/utility/result_of.hpp"
#include "boost/shared_ptr.hpp"
 
template<typename Thp, typename Func>
boost::shared_future< typename boost::result_of<Func()>::type >
submit_job(Thp& thp, Func f)
{
  typedef typename boost::result_of<Func()>::type result;
  typedef boost::packaged_task<result> packaged_task;
  typedef boost::shared_ptr<boost::packaged_task<result> > packaged_task_ptr;
 
  packaged_task_ptr task(new packaged_task(f));
  boost::shared_future<result> res(task->get_future());
  boost::threadpool::schedule(thp, boost::bind(&packaged_task::operator(), task));
 
  return res;
}

Here is a small example of its possible usage:

User lookup_user_in_database(int id) { ... }
...
int main()
{
  boost::threadpool::pool thp(3);//number of threads
  boost::shared_future<User> future = 
    submit_job(boost::bind(lookup_user_in_database, 10));
  while(!future.is_ready())
  { 
  //do something useful
  }
  User = future.get();
  ...
}

boost::futures are now finally officially shipped with boost starting with 1.41 release. boost::threadpool is not yet an official boost library, however you can find it here.

Much kudos to authors of these amazing libraries!

2 Responses to “Using boost::threadpool with boost::future”

  1. Denis Bazhenov Says:

    Conception of Futures very popular on Java Platform also. But there is one thing that I’m missing in Futures - asynchronous completition. Sometimes there is no need to wait for task to complete. All I need is to give task and completition function to thread pool. For example:

    Callable task = new LoadUserTask(userId);
    executor.submit(task, new CompletionHandler {
      public void onComplete(User user) {
        user.setLastLoginTime(now());
      }
    });

    Is there something similar in C++?

  2. pachanga Says:

    This should be very easy to achieve with a simple wrapper around the task. For example:

    template<typename Task, typename Callback
    struct TaskWithNotification
    {
      TaskWithNotification(Task t, Callback c)
        : task(t),
          callback(c)
      {}
     
      void operator()()
      {
         callback(task());
      }
    };

    …and the usage is straightforward:

    submit_job(
       threadpool, 
       TaskWithNotification(
         boost::bind(LoadUserTask, userId), 
         boost::bind(OnUserLoad, _1))
    );

    In C++0x completion handler can be a lambda.

Leave a Reply