2015-04-12 40 views
2

我正在使用boost interprocess library创建服务器和客户端程序,以便在共享内存中传递opencv mat objects。每个服务器和客户端进程都有两个boost线程,它们是boost :: thread_group的成员。一个处理命令行IO,另一个处理数据处理。共享内存访问使用boost :: interprocess condition_variables进行同步。已在条件变量等待调用中的中断提升线程

由于此程序涉及共享内存,因此我需要在退出之前执行一些手动清理。我的问题是,如果服务器提前终止,则客户端上的处理线程会在wait()调用中阻塞,因为服务器负责发送通知。我需要以某种方式中断阻止在wait()的线程来启动共享内存破坏。我知道在线程上调用interrupt()(在我的情况下为thread_group.interrupt_all())将导致在达到中断点(如wait())时引发boost::thread_interrupted异常,该中断点如果未处理,将允许共享内存销毁继续。但是,当我尝试在wait()中断线程时,似乎没有任何事情发生。例如,这个输出任何命令行:

try { 
    shared_mat_header->new_data_condition.wait(lock); 
} catch (...) { 
    std::cout << "Thread interrupt occurred\n"; 
} 

我不敢肯定,但它似乎像interrupt()需要调用线程进入wait()之前要抛出的异常发生。这是真的?如果没有,那么中断被condition_variable.wait()呼叫阻塞的升压线程的正确方法是什么?

感谢您的任何见解。

编辑 我接受了Chris Desjardins的答案,该答案不直接回答问题,但具有预期效果。在这里,我翻译了他使用的代码片段与boost::interprocess条件变量,它具有略微不同的语法比boost::thread条件变量:

while (_running) { 

    boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(1); 

    if (shared_mat_header->new_data_condition.timed_wait(lock, timeout)) 
    { 
     //process data 
    } 
} 

回答

2

我宁愿等待与超时,然后检查等待调用的返回码,看它是否超时与否。事实上,我有一个线程模式,我喜欢用它来解决这种情况(以及C++中线程的其他常见问题)。

http://blog.chrisd.info/how-to-run-threads/

你的主要观点是不是在一个线程无限阻塞,因此,你的线程应该是这样的:

while (_running == true) 
{ 
    if (shared_mat_header->new_data_condition.wait_for(lock, boost::chrono::milliseconds(1)) == boost::cv_status::no_timeout) 
    { 
     // process data 
    } 
} 

然后在你的析构函数您设置_running = FALSE;并加入线程。

+0

谢谢你,克里斯。这是我可以接受的一种变体,已被添加到我原始问题中的编辑中。我仍然有点困惑,因为切换到'timed_wait'调用,我尝试使用'thread_group.interrupt_all()'调用来查看是否因为timed_wait被输入并每毫秒自动退出,所以我可以得到抛出'boost :: thread_interrupted'异常。但是,仍然没有任何反应。如果你对中断不起作用有任何想法,那会很好。 – jonnew

+0

嗯 - 我想我明白了。我正在使用'boost :: interprocess'条件变量。这里引用的中断点(http://www.boost.org/doc/libs/1_57_0/doc/html/thread/thread_management.html#interruption_points)可能仅适用于'boost :: condition_variable'比'boost :: interprocess :: condition_variable'。 – jonnew

+0

正如你所说,我的想法是:当你所做的只是多线程时,不要使用进程间通信结构。 –

0

尝试使用“通知功能”。保持一个指向你的条件变量的指针,并调用它而不是中断线程。中断比通知电话昂贵得多。

因此而不是做

thread_group.interrupt_all() 

调用这个代替

new_data_condition_pointer->notify_one() 
+0

我不确定我完全理解。至少现在,只有服务器通知客户端。由于服务器进程已终止,因此不能再发出通知调用以使客户端脱离“wait()”。客户端线程停留在'wait()'中,所以不能发出'notify_one()'调用。我猜想的想法是保持'new_data_condition_pointer'在第二个IO线程上,并使用它在服务器故障后发出通知? – jonnew