我有一个服务器类型的应用程序,并且在确保线程在完成之前不会被删除。下面的代码几乎代表我的服务器;需要进行清理以防止在列表中建立死线。处理多线程清理的最佳方式
using namespace std;
class A {
public:
void doSomethingThreaded(function<void()> cleanupFunction, function<bool()> getStopFlag) {
somethingThread = thread([cleanupFunction, getStopFlag, this]() {
doSomething(getStopFlag);
cleanupFunction();
});
}
private:
void doSomething(function<bool()> getStopFlag);
thread somethingThread;
...
}
class B {
public:
void runServer();
void stop() {
stopFlag = true;
waitForListToBeEmpty();
}
private:
void waitForListToBeEmpty() { ... };
void handleAccept(...) {
shared_ptr<A> newClient(new A());
{
unique_lock<mutex> lock(listMutex);
clientData.push_back(newClient);
}
newClient.doSomethingThreaded(bind(&B::cleanup, this, newClient), [this]() {
return stopFlag;
});
}
void cleanup(shared_ptr<A> data) {
unique_lock<mutex> lock(listMutex);
clientData.remove(data);
}
list<shared_ptr<A>> clientData;
mutex listMutex;
atomc<bool> stopFlag;
}
这个问题似乎是,析构函数在错误的顺序运行 - 即shared_ptr的是线程的函数结束时在破坏,这意味着“A”对象的线程完成之前被删除,造成了Havok当线程的析构函数被调用。
即 通话中移除清理功能 这一切的引用(即一个的目的),那么再次调用析构函数(包括该线程的析构函数) 调用该线程的析构函数 - 糟糕!
我看了一些替代品,比如维护一个'被删除'列表,这个列表定期用来清理另一个线程的主列表,或者为共享指针使用一个延时的deletor函数,但是这两个这些看起来矮胖,可能有竞争条件。
任何人都知道一个很好的方法来做到这一点?我看不到一个简单的重构方法,它可以正常工作。
你能举一些例子吗? – 4pie0
@lizusek一个什么样的例子?我提出了几种不同的解 –
如何创建收割者线程的示例;一个什么也不做,只能加入任何未完成的线程的线程,在它们之后进行清理。 – 4pie0