我正在使用boost线程来并行化程序中的计算。控制器对象管理计算作业和结果。我创建了一堆工作线程,当主线程显示结果时,它们从控制器对象获取作业。结果需要以正确的顺序显示。为实现这一点,我在std::deque
中使用了boost期货。 GetNewJob()
在双端队列的末尾添加一个新的boost::promise
并返回一个指针。 GetNextResult()
从队列的前端获取结果。如果还没有准备好结果,它会阻塞调用线程。
我的Controller类的重要部分:
class Controller
{
public:
Controller();
boost::shared_ptr<boost::promise<Results> > GetNewJob();
Results GetNextResult();
class NoJobsLeft{};
class NoResultsLeft{};
private:
bool JobsLeft() const;
bool ResultsLeft() const;
std::deque<boost::shared_ptr<boost::promise<Results> > > queue_;
boost::mutex mutex_;
boost::condition_variable condition_;
};
工人职能:
void DoWork()
{
try
{
while(true)
{
boost::shared_ptr<boost::promise<Results> >
promise(controller.GetNewJob());
//do calculations
promise->set_value(results);
}
}
catch(NoJobsLeft)
{
}
}
主程序代码:
Controller controller(args);
boost::thread_group worker_threads;
for (unsigned i = 0; i < n_cpus; ++i)
worker_threads.create_thread(DoWork);
try
{
while(true)
{
Results results = controller.GetNextResult();
std::cout << results;
std::cout << std::endl;
}
}
catch(NoResultsLeft)
{
}
worker_threads.join_all();
有时这很好用,所有结果都会显示出来。 但很多时候我根本看不到任何输出。
我不在工作线程中使用cout
。
GetNewJob()
,GetNextResult()
的实施:
boost::shared_ptr<boost::promise<Results> > Controller::GetNewJob()
{
boost::lock_guard<boost::mutex> lock(mutex_);
if (!JobsLeft())
throw NoJobsLeft();
//determine more information about the job, not important here
queue_.push_back(boost::make_shared<boost::promise<Results> >());
condition_.notify_one();
return queue_.back();
}
Results Controller::GetNextResult()
{
boost::shared_ptr<boost::promise<Results> > results;
{
boost::unique_lock<boost::mutex> lock(mutex_);
if (!ResultsLeft())
throw NoResultsLeft();
while(!queue_.size())
{
condition_.wait(lock);
}
results = queue_.front();
queue_.pop_front();
}
return results->get_future().get();
}
bool Controller::ResultsLeft() const
{
return (queue_.size() || JobsLeft()) ? true : false;
}
答案 0 :(得分:2)
如果您没有看到任何输出,则可能会抛出NoResultsLeft
,因为第一次传递队列中没有任何内容。另一种可能性是它首先没有向队列添加内容或者抛出NoJobsLeft
。在catch块中添加std::cout
语句可能有助于识别正在发生的事情。
但是,如果结果无法异步显示,那么您没有理由等待所有这些机制。不能保证线程完成顺序只是通过boost::promise
将结果添加到队列的顺序,因此您必须至少在GetNextResult
中阻塞,直到第一个线程完成为止。< / p>
如果您想要按顺序显示结果,您的控制器可以采用相同的方式收集所有结果并触发boost::function
,以便在一切就绪后以正确的顺序显示结果。
修改强>
BTW while(!queue_.size())
确实应该是while(queue_.empty())
而技术上任何非零都被解释为名为size()
,length()
的真实方法,等等当用作如果条件。同样适用于return (queue_.size() || JobsLeft()) ? true : false;
return (!queue.empty() || JobsLeft());