Получение возвращаемого значения из функции-члена boost::threaded?
-
19-09-2019 - |
Вопрос
У меня есть рабочий класс, подобный приведенному ниже:
class Worker{
public:
int Do(){
int ret = 100;
// do stuff
return ret;
}
}
Он предназначен для выполнения с помощью boost::thread и boost::bind, например:
Worker worker;
boost::function<int()> th_func = boost::bind(&Worker::Do, &worker);
boost::thread th(th_func);
th.join();
Мой вопрос: как мне получить возвращаемое значение Worker::Do?
Заранее спасибо.
Решение
Я не думаю, что вы сможете получить возвращаемое значение.
Вместо этого вы можете сохранить значение как член Worker:
class Worker{
public:
void Do(){
int ret = 100;
// do stuff
m_ReturnValue = ret;
}
int m_ReturnValue;
}
И используйте его так:
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
Другие советы
Другой вариант — использовать обещания/фьючерсы.
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.
И если вы можете использовать c++0x, то использование std::async упакует все вышеперечисленное и просто сделает:
std::future<int> f = std::async( std::bind(&Worker::Do, &worker) );
int retval = f.get(); //Will block until do returns an int.
Кроме того, у вас также есть несколько избыточных вызовов boost::bind() и boost::function().Вместо этого вы можете сделать следующее:
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));
Вы можете сделать это, поскольку конструктор Thread представляет собой удобную оболочку внутреннего вызова метода связывания(). Конструктор потоков с аргументами
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();
Вы можете взглянуть на концепцию «boost::future», см. это связь
Другой вариант — использовать Boost.Лямбда библиотека.Затем вы можете написать код следующим образом, не меняя Worker
сорт:
Worker worker;
int ret;
boost::thread th( boost::lambda::var( ret ) = worker.Do() );
th.join();
Это особенно полезно, когда вы не можете изменить вызываемую функцию.Таким образом, возвращаемое значение заворачивается в локальную переменную. ret
.