Как ждать, пока мьютекс не разблокируется? - PullRequest
3 голосов
/ 01 декабря 2011

Существует массив мьютексов. Моя функция:

  1. Проверяет, заблокирован ли мьютекс

2a. Если нет, то блокирует его

2b. Если заблокировано, дождитесь разблокировки и заблокируйте его

Другая функция разблокирует его.

Проблема в том, что у меня произошел сбой в секции ожидания:

HANDLE mutexes[N];

void func(int i)
{
  // (*) wait until unlocked or create if unlocked
  while ((mutexes[i] = CreateMutex(NULL, TRUE/*same with FALSE*/, NULL)) != NULL);
  /*or WaitForSingleObject(mutexes[i], INFINITE)*/

  mutexes[i] = CreateMutex(NULL, TRUE, NULL);
}

В (*) моменте у меня произошел сбой - нарушение прав доступа. Сбой происходит при попытке создать мьютексы [i], которые уже были созданы ранее. Я не могу использовать WaitForSingleObject, потому что в первый раз мьютексы [i] не создаются и в документах говорится, что WaitForSingleObject не определен. Также, если я использую эту функцию, я получаю тот же сбой.

Все, что мне нужно, это аналог такого простого псевдокода

if (mutex_has_been_created[mutexes[i]])
  WaitUntilRelease()
CreateMutex();

Я попытался обернуть его в критическом разделе и получил тот же результат. Я уверен, что i находится в правильном диапазоне. Я не могу использовать Boost / pThreads / и т.д.

Я знаю, что моя проблема довольно проста, но я не могу найти решение. Во всех примерах, которые я видел, мьютекс создается до WaitForSingleObject, у меня это не работает.

Спасибо.

Ответы [ 4 ]

15 голосов
/ 01 декабря 2011

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

Кратко:

  1. CreateMutex инициализирует ("создает") мьютекс.
  2. WaitForSingleObject и др. Заблокировать мьютекс (или тайм-аут).
  3. ReleaseMutex открывает его.
  4. CloseHandle уничтожает его.

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

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

4 голосов
/ 01 декабря 2011

Если вы хотите подождать, пока он не будет разблокирован, только чтобы заблокировать его, то вы можете просто заблокировать его.Это именно то, что происходит, когда вы делаете это.При попытке блокировки код блокируется, пока мьютекс не станет доступным, а затем блокирует его.

1 голос
/ 01 декабря 2011
HANDLE mutexes[N]

void InitMutexes(int N)
{
    for (int i =0; i < N ; i++)
    {           
        mutexes[i] = CreateMutex( NULL, FALSE, NULL);
    }
}
void WaitForMutex(int n)
{
    WaitForSingleObject(mutexes[n], INFINITE);
}
void ReleaseMutex(int n)
{
    ReleaseMutex(mutexes[n]);
}
void CleanUpMutexes(int N)
{
    for (int i=0; i < N; i++)
    {
          ReleaseMutex(mutexes[i]); CloseHandle(mutexes[i]);
    }
}

Надеюсь, это поможет.

1 голос
/ 01 декабря 2011

В потоках posix вы, вероятно, будете использовать условные переменные ; Я понятия не имею, предлагают ли WinAPI подобные вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...