2015-06-26 108 views
1

我的对象创建了一个线程,该线程在其生命周期中修改了对象创建者。问题是,线程在销毁时不应该调用对象方法。我已经找到了一些解决方案,我想知道这是否是最好的。测试对象是否未被删除

class A 
{ 
    shared_ptr<int> guard = make_shared<int>(0); 
public: 
    weak_ptr<int> getGuard() { return guard; } 
    void method() {} 
    A() 
    { 
     thread([this] 
     { 
      const auto &guard = getGuard(); 
      while(!guard.expired()) 
       method(); 
     }); 
    } 
}; 
+1

您是否打算分离创建的线程,以便线程不会阻塞'A'的构造函数? –

+0

是的,在现实生活中,线程构造不会阻塞主线程。说实话,新的线程甚至没有在构造函数中创建。我只是试图简化示例。 –

回答

1

如果你想确保当你调用method对象不被破坏,但可以在其他时间被摧毁,则需要保留对象本身的weak_ptr,并在调用方法时锁定该对象。喜欢的东西:

class A : std::enable_shared_from_this<A> 
{ 
public: 
    void method() {} 
    A() 
    { 
     std::weak_ptr<A> self(shared_from_this()); 
     thread([=self] 
     { 
      while (auto This = self.lock()) 
       This->method(); 
     }).detach(); 
    } 
}; 

这个对象现在只能通过make_shared创造的 - 试图做到这一点不确定的行为任何其他方式的结果,并可能会崩溃。

3

while循环,你有没有保证method而指向的对象guard仍然只存在被称为线程安全的方式。原因是另一个线程可能会导致在expired的调用和method的调用之间的对象被破坏。

执行此检查的安全的方法是试图推动弱指针的共享指针:

while (true) 
{ 
    shared_ptr<int> sp = getGuard().lock(); 
    if (sp) 
    { 
     method(); 
    } 
    else 
    { 
     return; 
    } 
} 

通过促进弱指针的共享指针,调用代码参与对象的所有权在拨打method的过程中,确保在调用代码正在使用它时不会被销毁。

您也未能加入或分离线程。在你的例子中,它看起来像你想分离它,以便A的构造函数可以在线程完成执行前退出。在这种情况下,你的代码应该是这样的:

thread([this] 
{ 
    ... 
}).detach(); 
+0

你的答案的第一部分对我来说非常重要。我忽略了那个线程不安全。指针提升不会有帮助(它指向一个类的成员,而不是一个对象),但是用一些互斥锁包装这些行将完成这项工作。 这是一些伪代码来说明整体想法,无论如何感谢关于detach()的建议。 谢谢! –

+0

这并没有真正的帮助 - 锁只会阻止共享的'int'而不是对象的销毁。所以你仍然可以获得锁,然后另一个线程销毁该对象,然后调用被销毁对象的方法。你需要为对象本身保留一个'weak_ptr',并锁定它。 –

+0

@Chris Dodd你是对的,我没有正确地思考所有的细节,我更关心while循环检查。随意编辑这个答案或留下一个新的,否则我将不得不稍后回来,以确保细节得到补充。 –

相关问题