Повысить named_mutex и удалить () - PullRequest
       36

Повысить named_mutex и удалить ()

8 голосов
/ 26 сентября 2011

У меня есть класс, который может быть создан несколькими потоками.Но в одной функции код должен быть защищен, поэтому я решил использовать буст-мьютекс между процессами.Каждый класс создает или открывает один и тот же Mutex в своем конструкторе:

MyClass::MyClass()
{
       boost::interprocess::named_mutex m_Lock(
                 boost::interprocess::open_or_create, "myLock" );
}

Так что теперь наступает момент, когда критическая часть кода вызывается:

int MyClass::MyFunction()
{
       boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(
                  m_Lock, boost::interprocess::try_to_lock);
       if(!lock)
       {
           return -1;
       }
       // else do some stuff here 
}

Очистить после функции(и как это описано на странице повышения) Я использую команду удаления в деструкторе своего класса:

MyClass::~MyClass()
{
       boost::interprocess::named_mutex::remove("myLock");
}

На самом деле весь этот код работает нормально, но у меня есть одна проблема:

Как сказано в описании команды удаления:

Стирает именованный мьютекс из системы.Возвращает false при ошибке.Никогда не бросает.

Это означает, что команда удаления просто удаляет мьютекс из системы - даже если другой поток только что заблокировал его (я уже пробовал этот случай - он больше не заблокирован).Поэтому моя проблема заключается в следующем: например, у меня есть 3 потока (A, B и C) - теперь происходит следующее:

  1. Процесс A создает экземпляр класса, вызывает функцию и блокирует ее
  2. Процесс B создает экземпляры класса, вызывает функцию, но не может получить доступ к коду (затем ожидает, например)
  3. Процесс A завершает работу с защищенным кодом и разблокируется
  4. Процесс B получает доступ к защищенному коду и блокирует его
  5. Процесс A удаляет экземпляр класса -> команда удаления называется
  6. Процесс C создает экземпляр класса, вызываетфункция и может получить доступ к коду, так как команда удаления стерла Mutex -> Ошибка!

Так что теперь кто-то может сказать: «Тогда не вызывайте удалить!» - Ну, это возможно?Я имею в виду, что так как named_mutex пишет в систему, я сомневаюсь, что он стирается без явного вызова, даже если программа заканчивается.У кого-нибудь есть помощь?

Ответы [ 2 ]

6 голосов
/ 27 сентября 2011

Из boost docs вызов remove не требуется. Деструктор named_mutex автоматически позаботится о том, чтобы ОС указала, что процессу больше не нужны ресурсы. Вы, вероятно, в порядке, просто полагаясь на встроенное поведение деструктора для очистки.

Если вы явно вызовите remove, вы, вероятно, вызовете сбой любых других процессов или потоков, использующих именованный мьютекс, при выполнении любых операций с мьютексом. В зависимости от того, как ваше использование организовано, это может привести либо к скачкам данных, либо к сбоям / исключениям в других процессах.

~ named_mutex ();

Уничтожает * это и указывает, что вызывающий процесс завершен используя ресурс. Функция деструктора освобождает любую систему ресурсы, выделенные системой для использования этим процессом для этого ресурс. Ресурс все еще может быть открыт снова, вызывая open перегрузка конструктора. Для удаления ресурса из системы используйте удалить ().

0 голосов
/ 26 сентября 2011

Возможно, вам нужен общий счетчик использования мьютекса. Заблокируйте мьютекс в деструкторе, уменьшите его, и если после декремента он станет равным нулю, освободите все еще заблокированный мьютекс. Тем самым вы предотвратите текущее состояние вашей гонки.

...