[英]Program output appears only sometimes in multi-threaded program
I'm using boost threads to parallelize the calculations in my program. 我正在使用boost线程来并行化程序中的计算。 A controller object manages the calculation jobs and the results.
控制器对象管理计算作业和结果。 I create a bunch of worker threads which get their jobs from the controller object while the main thread displays the results.
我创建了一堆工作线程,当主线程显示结果时,它们从控制器对象获取作业。 The results need to be shown in the correct order.
结果需要以正确的顺序显示。 To achieve this I use boost futures in a
std::deque
. 为了达到这个目的,我在
std::deque
使用了boost期货。 GetNewJob()
adds a new boost::promise
to the end of the deque and returns a pointer. GetNewJob()
在双端队列的末尾添加一个新的boost::promise
并返回一个指针。 GetNextResult()
takes a result from the front end of the queue. GetNextResult()
从队列的前端获取结果。 If no result is ready yet, it blocks the calling thread. 如果还没有准备好结果,它会阻塞调用线程。
The important parts of my Controller class: 我的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_;
};
Worker function: 工人功能:
void DoWork()
{
try
{
while(true)
{
boost::shared_ptr<boost::promise<Results> >
promise(controller.GetNewJob());
//do calculations
promise->set_value(results);
}
}
catch(NoJobsLeft)
{
}
}
Main program code: 主程序代码:
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();
Sometimes this works just fine, all results are displayed. 有时这很好用,所有结果都会显示出来。 But very often I cannot see any output at all.
但通常我根本看不到任何输出。
I do not use cout
in the worker threads. 我不在工作线程中使用
cout
。
Implementations of GetNewJob()
, GetNextResult()
: 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;
}
In the case where you don't see any output it could be throwing NoResultsLeft
because nothing is in the queue on the first pass. 如果您没有看到任何输出,则可能会抛出
NoResultsLeft
因为第一次传递队列中没有任何内容。 The other possibility is that it is failing to add things to the queue in the first place or throwing NoJobsLeft
. 另一种可能性是它首先没有向队列添加内容或者抛出
NoJobsLeft
。 Adding std::cout
statements into your catch blocks might help identify what's going on. 将
std::cout
语句添加到catch块中可能有助于识别正在发生的事情。
However if the results can't be displayed asynchronously then there is no reason for the mechanism you might as well wait all. 但是,如果结果无法异步显示,那么您没有理由等待所有这些机制。 There is no guarantee of the order of completion of threads only the order in which you add the results to the queue via
boost::promise
so you have to block anyway in GetNextResult
at least until the first thread completes. 不能保证线程完成顺序只是通过
boost::promise
将结果添加到队列的顺序,所以你必须至少在GetNextResult
中阻塞,直到第一个线程完成。
If you want to display results sequentially your controller could gather all results in the same way and fire a boost::function
to display the results in the correct order when everything is ready. 如果要按顺序显示结果,控制器可以以相同的方式收集所有结果并触发
boost::function
,以便在所有内容准备就绪时以正确的顺序显示结果。
Edit: 编辑:
BTW while(!queue_.size())
really ought to be while(queue_.empty())
while technically anything non-zero is interpreted as true methods named size()
, length()
, etc really look ugly when used as an if condition. BTW
while(!queue_.size())
真的应该是while(queue_.empty())
而技术上任何非零被解释为名为size()
真实方法, length()
等在用作时非常丑陋如果条件。 Same goes for return (queue_.size() || JobsLeft()) ? true : false;
return (queue_.size() || JobsLeft()) ? true : false;
return (queue_.size() || JobsLeft()) ? true : false;
which could be return (!queue.empty() || JobsLeft());
哪个可以
return (!queue.empty() || JobsLeft());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.