Я знаю, я знаю, заголовок моего сообщения может казаться провокационным, начиная с повышения:: взаимное исключение целеустремленно не представляет блокировку / разблокировали (для предотвращения тупиков).
Однако документация повышения довольно коротка на этих аспектах (по меньшей мере), таким образом, я спрашиваю, может ли кто-либо помочь мне в следующем варианте использования.
Предположим, что у Вас есть класс Foo, который имеет:
- деструктор, который занимает время для завершения
- метод, который называет отличный поток, но нельзя назвать во время разрушения
class Foo
{
public:
virtual ~Foo()
{
//Time consuming operations here
}
//Method called by a timer belonging to a distinct class
void OnTimer()
{
//Other time consuming stuff. Should not be called during destruction !
}
};
Я пытался (без успеха) реализовать версию на основе повышения:: взаимное исключение
//boost::mutex implementation
class Foo
{
public:
Foo()
{
}
virtual ~Foo()
{
{
boost::mutex::scoped_lock lock(mDisposingMutex);
//Time consuming operations here
}
}
//Method called by a timer belonging to a distinct class
void OnTimer()
{
{
//Imaginary code here: mutex::locked() method is private !!!
if ( ! mDisposingMutex.locked())
return;
}
//Other time consuming stuff. Should not be called during destruction !
}
private:
boost::mutex mDisposingMutex;
};
Я полностью неправильно? Может любой говорить мне, как это, как предполагается, сделано с повышением:: взаимное исключение?
Спасибо!
Если вы действительно используете Lockable :: lock ()
в теле деструктора, вы можете использовать функцию OnTimer ()
Lockable :: try_lock ()
, и продолжайте, только если эта функция возвращает истину. Это заставит OnTimer ()
приостановить деструктор, если OnTimer ()
запустится первым, но по-прежнему не решает проблему запуска деструктора, завершение и освобождение мьютекса, а затем запуск OnTimer ()
и успешный захват мьютекса.
Такая последовательность, скорее всего, относится к области неопределенного поведения, но это проклятие не остановит ее. Использование государственного флага в дополнение к мьютексу - аналогично тому, что я описал в моем комментарии выше - может позволить вам обнаружить этот последний случай и остановить OnTimer ()
от выполнения каких-либо действий. помимо чтения флага. Однако в какой-то момент это просто заменяет пластыри пластырями.
@Seh: Я полностью согласен, что это запах кода, и я должен (и буду) исправлять основную причину.
Тем не менее, в надежде помочь любому, кто столкнется с той же проблемой, что и я (т. Е. Бороться с документацией по ускорению), я попытался реализовать ваше предложение. Приведенный ниже код теперь компилируется правильно (хотя запах кода теперь очень сильный)
#include <boost/thread/mutex.hpp>
//boost::mutex implementation
class Foo
{
public:
Foo() :
mIsDisposing(false)
{
}
virtual ~Foo()
{
{
boost::try_mutex::scoped_try_lock lock(mDisposingMutex);
if ( ! lock.locked())
{
//Die by horrible death, or wait before trying again...
}
else
{
mIsDisposing = true;
}
//Time consuming operations here
}
}
//Method called by a timer belonging to a distinct class
void OnTimer()
{
{
boost::try_mutex::scoped_try_lock lock(mDisposingMutex);
if ( ! lock.locked() || mIsDisposing )
{
return;
}
}
//Other time consuming stuff. Should not be called during destruction !
}
private:
boost::try_mutex mDisposingMutex;
bool mIsDisposing;
};