I've been using std::mutex lately and is now looking for a pattern/design guide on deleting an object that has std::mutex as member. The problem arises when an object as a public function that uses the mutex(monitor function, critical section, etc) and when this object is deleted, it might have threads still waiting on the mutex. std::mutex have undefined behavior deleted while being locked by other thread, and so the problem arises.
I want to know what is a generally acceptable pattern to use in this case. Or if this is considered a bad coding style, a way to avoid this design, ie) do not delete an object whose mutex methods are still being waited on.
Example:
//a public method that uses mutex.
IAsyncAction^ XInputBase::flushTask()
{
return create_async([this](){
_monitorMutex.lock();
if (_readyToFlush && !_noMoreFlush) {
//should flush only once, block additional flush signals.
_noMoreFlush = true;
_monitorMutex.unlock();
//actually flush
concurrency::task<void> UITask = concurrency::create_task(Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([=]()
{
onFlush();
})));
}
else {
_needToFlush = true;
_monitorMutex.unlock();
}
});
}
Tried solutions: Destructor waiting for mutex to completely unlock after all waiting threads are processed. I've implemented it by setting a flag outside of mutex, so that all threads in the method are either exiting or waiting on the mutex. Then I've locked the std::mutex for last time at destructor. Given that the std::mutex is fair, destructor should be unlocked last after other waiting threads are processed, then destroy the object.
This doesn't work because std::mutex does not guarantee fairness in most platforms.
Sort of working solution: Implement the object as a ref class or other reference counted object(smart pointers). Then implement the concurrent method as a lamda that holds a strong reference to the object. Once all other objects holding this object are deleted and all lamdas with mutexes are processed, this object will be deleted automatically.
I don't like this method as it poses some restriction on the rest of the code. For WinRT, this method does not give control which thread deletes this object, as a result, UI thread error can occur.
Aucun commentaire:
Enregistrer un commentaire