最近遇到一個問題,
我們的程式庫設計成有自己的worker thread
負責回覆客戶端一些資訊(用意是讓main thread專心處理UI)
下面的code是一個簡化的例子
template<typename Handler>
class Worker : public WorkerBase
{
mutex mtx_;
condition_variable cond_;
thread thrd_;
Handler handler_;
public:
Worker(Handler handler) : handler_(handler)
{
mutex::scoped_lock lock(mtx_);
thread(ref(*this)).swap(thrd_);
}
~Worker(void)
{
thread thrd;
mutex::scoped_lock lock(mtx_); // wait callback return
thrd.swap(thrd_);
cond_.notify_one();
lock.unlock();
thrd.join();
}
void operator()(void)
{
mutex::scoped_lock lock(mtx_);
while (thrd_.joinable())
{
handler_(); // SB calls Worker::~Worker()
cond_.wait(lock);
}
}
};
顯而易見如果在handler_()裡再呼叫~Worker()就會deadlock
原本上面提示我用reference count,實作後發現會違反另一個需求:
由main thread呼叫~Worker()與callback是同步的(如範例所示)
之後我看了asio的精妙作法,想提出來問這樣改是否ok
首先加入dispose(),之後不直接呼叫~Worker()
void Worker::dispose(void)
{
if (asio::detail::call_stack<Worker>::contains(this))
{
thread(bind(&checked_delete, this)).detach();
}
else
checked_delete(this);
}
並在operator()中加入:
asio::detail::call_stack<Worker>::context ctx(this);
簡單的說就是拿asio::detail::call_stack來判斷是否在callback中
試著結束worker thread,是則用另一個thread來完成這件事
否則(是在main thread中)就照原設計join worker thread
想請問板上的先進們這樣做會不會有潛在的危機?
亦或是有更好的作法嗎?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 123.204.92.148