повышение:: взаимное исключение / Как протестировать, если взаимное исключение заблокировано

Я знаю, я знаю, заголовок моего сообщения может казаться провокационным, начиная с повышения:: взаимное исключение целеустремленно не представляет блокировку / разблокировали (для предотвращения тупиков).

Однако документация повышения довольно коротка на этих аспектах (по меньшей мере), таким образом, я спрашиваю, может ли кто-либо помочь мне в следующем варианте использования.

Предположим, что у Вас есть класс 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; 
}; 

Я полностью неправильно? Может любой говорить мне, как это, как предполагается, сделано с повышением:: взаимное исключение?

Спасибо!

9
задан Pascal T. 15 December 2009 в 01:49
поделиться

3 ответа

Если вы действительно используете Lockable :: lock () в теле деструктора, вы можете использовать функцию OnTimer () Lockable :: try_lock () , и продолжайте, только если эта функция возвращает истину. Это заставит OnTimer () приостановить деструктор, если OnTimer () запустится первым, но по-прежнему не решает проблему запуска деструктора, завершение и освобождение мьютекса, а затем запуск OnTimer () и успешный захват мьютекса.

Такая последовательность, скорее всего, относится к области неопределенного поведения, но это проклятие не остановит ее. Использование государственного флага в дополнение к мьютексу - аналогично тому, что я описал в моем комментарии выше - может позволить вам обнаружить этот последний случай и остановить OnTimer () от выполнения каких-либо действий. помимо чтения флага. Однако в какой-то момент это просто заменяет пластыри пластырями.

6
ответ дан 4 December 2019 в 19:34
поделиться

mutex :: try_lock ()

2
ответ дан 4 December 2019 в 19:34
поделиться

@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;
};
4
ответ дан 4 December 2019 в 19:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: