8

I have a worker class like the one below:

class Worker{
public:
  int Do(){
    int ret = 100;
    // do stuff
    return ret;
  }
}

It's intended to be executed with boost::thread and boost::bind, like:

Worker worker;
boost::function<int()> th_func = boost::bind(&Worker::Do, &worker);
boost::thread th(th_func);
th.join();

My question is, how do I get the return value of Worker::Do?

Thanks in advance.

He Shiming
  • 5,710
  • 5
  • 38
  • 68

5 Answers5

13

Another option is to use promises/futures.

class Worker{
public:
  void Do( boost::promise<int> & p){
    int ret = 100;
    // do stuff
    p.set_value(ret);
  }
};
//Later...
boost::promise<int> p;
boost::thread t( boost::bind(&Worker::Do, &worker, boost::ref(p));
int retval = p.get_future().get(); //This will block until the promise is set.

And if you can use c++0x, then using std::async will package up all of the above and just do:

std::future<int> f = std::async( std::bind(&Worker::Do, &worker) );
int retval = f.get(); //Will block until do returns an int.
tgoodhart
  • 3,111
  • 26
  • 37
8

I don't think you can get the return value.

Instead, you can store the value as a member of Worker:

class Worker{
public:
  void Do(){
    int ret = 100;
    // do stuff
    m_ReturnValue = ret;
  }
  int m_ReturnValue;
}

And use it like so:

Worker worker;
boost::function<void()> th_func = boost::bind(&Worker::Do, &worker);
boost::thread th(th_func);
th.join();
//do something with worker.m_ReturnValue
Alex Deem
  • 4,717
  • 1
  • 21
  • 24
3

In addition, you also have some redundant calls to boost::bind() and boost::function(). You can instead do the following:

class Worker{
    public:
       void operator(){
          int ret = 100;
          // do stuff
          m_ReturnValue = ret;
       }
    int m_ReturnValue;
}

Worker worker;
boost::thread th(worker());//or boost::thread th(boost::ref(worker));

You can do this because Thread's constructor is a convenience wrapper around an internal bind() call. Thread Constructor with arguments

Imran.Fanaswala
  • 755
  • 4
  • 6
  • That looks quite straightforward. Thanks but my actual implementation contains many member functions, so I can't really use the () operator. – He Shiming Nov 12 '09 at 01:58
  • @He Shiming: You can still use it without bind(). For example, boost::thread(worker(),&Worker::Do) (The syntax may be slightly off since its the top of my of head). – Imran.Fanaswala Nov 12 '09 at 10:14
1
class Worker{
public:
  int Do(){
  int ret = 100;
  // do stuff
  return ret;
  }
}

Worker worker;
boost::packaged_task<int> ptask(boost::bind(&Worker::Do, &worker));
boost::unique_future<int> future_int = ptask.get_future();
boost::thread th(boost::move(ptask));
th.join();
if (future_int.is_ready())
   int return_value = future_int.get();

You can take a look at the "boost::future" concept, ref this link

Marx Yu
  • 351
  • 5
  • 8
-2

Another option is using the Boost.Lambda library. Then you can write the code as follows without changing the Worker class:

Worker worker;
int ret;
boost::thread th( boost::lambda::var( ret ) = worker.Do() );
th.join();

This is useful in particular when you cannot change the function to call. Like this, the return value is wrapped in a local variable ret.

Mathias Soeken
  • 1,293
  • 2
  • 8
  • 22
  • 5
    This will execute `worker.Do()` in the current thread, copy the result into a lambda object, run that lambda on the new thread (thus assigning the result of `worker.Do()` to `ret`), and then wait for the execution of the new thread to complete. This is most likely **not** the desired behaviour, because it executes `worker.Do()` in the wrong thread. The easiest correct way to get results back from a function executed in a different thread is to use futures and promises. – Mankarse Jan 31 '12 at 16:58