确保您分配的内存是拥有的
确保每个分配的内存都由一个智能指针拥有,无论是 C++03 的 auto_ptr、C++11 的 unique_ptr 还是 Boost 的 scoped_ptr,甚至是shared_ptr(可以共享、复制和移动)。
这样,RAII 将保护您免受任何内存泄漏。
礼貌地阅读中断,Herb Sutter 的一篇文章解释了中断线程的各种方法。
今天使用Boost.Thread 1.37,您可以通过抛出异常来要求线程终止。在 Boost 中,是 boost::thread_interrupted 异常,它会从任何中断点抛出异常。
因此,您不需要处理某种消息循环,或验证某些全局/共享数据。主线程通过异常请求工作线程停止,一旦工作线程到达中断点,就会抛出异常。前面描述的 RAII 机制将确保您分配的所有数据都将被正确释放。
假设您有一些将在线程中调用的伪代码。它可能是一个可能会分配内存的函数,另一个会在循环内进行大量计算:
Object * allocateSomeObject()
{
Object * o = NULL ;
if(/*something*/)
{
// Etc.
o = new Object() ;
// Etc.
}
return o ; // o can be NULL
}
void doSomethingLengthy()
{
for(int i = 0; i < 1000; ++i)
{
// Etc.
for(int j = 0; j < 1000; ++j)
{
// Etc.
// transfert of ownership
Object * o = allocateSomeObject() ;
// Etc.
delete o ;
}
// Etc.
}
}
上面的代码不安全,如果不采取措施确保内存始终由 C++ 对象(通常是智能指针)拥有,则无论中断模式如何都会泄漏。
可以通过这种方式对其进行修改,以使代码既可中断又内存安全:
boost::shared_ptr<Object> allocateSomeObject()
{
boost::shared_ptr<Object> o ;
if(/*something*/)
{
// Etc.
boost::this_thread::interruption_point() ;
// Etc.
o = new Object() ;
// Etc.
boost::this_thread::interruption_point() ;
// Etc.
}
return o ; // o can be "NULL"
}
void doSomethingLengthy()
{
for(int i = 0; i < 1000; ++i)
{
// Etc.
for(int j = 0; j < 1000; ++j)
{
// Etc.
// transfert of ownership
boost::shared_ptr<Object> o = allocateSomeObject() ;
// Etc.
boost::this_thread::interruption_point() ;
// Etc.
}
// Etc.
boost::this_thread::interruption_point() ;
// Etc.
}
}
void mainThread(boost::thread & worker_thread)
{
// etc.
if(/* some condition */)
{
worker_thread.interrupt() ;
}
}
不使用升压?
如果你不使用 Boost,那么你可以模拟这个。如果线程应该被中断,则将一些线程存储布尔变量设置为“true”。添加检查此变量的函数,如果为真,则抛出特定异常。让线程的“根”捕获此异常以使其正确结束。
免责声明
我现在无法访问 Boost 1.37,所以我无法测试之前的代码,但想法就在那里。我会尽快对此进行测试,并最终发布更完整/正确/可编译的代码。