события — частичный мьютекс C ++ / блокировка критической секции

Я работаю в C ++ в VS2010, и у меня есть контейнерный класс с кучей свойств (геттеры и сеттеры) (на самом деле это куча объектов со свойствами — но давайте упростим его и предположим, что это просто свойства непосредственно в классе контейнера.

В этом классе контейнеров есть функция Update, и важно, чтобы методы setters были заблокированы во время выполнения метода Update.

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

Мой вопрос: как я могу блокировать / блокировать сеттеры, когда метод Update работает, не позволяя методам сеттера блокировать друг друга? Кроме того, мне также понадобятся сеттеры, чтобы заблокировать метод обновления.

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

Заранее спасибо,
Мартин

3

Решение

Если не требуется одновременной защиты сеттеров (например, setPropertyX (значение)), это выполнимо с помощью одного семафора и сбрасываемого вручную события, где начальный счетчик ресурсов — это количество свойств, от которых вы защищаете.

в любом заданном сеттере:

  • Ждите NoUpdatePendingEvent как установлено.
  • Получить ресурс семафора (1)
  • Обновить значение свойства
  • Освободить семафорный ресурс (1)

в основной процедуре обновления

  • Событие NoUpdatePending очищено
  • Получить ресурсы семафора (n)
  • Сделать обновление
  • Освободить ресурсы семафора (n)
  • NoUpdatePending набор событий

где (n) — количество имеющихся у вас свойств. Начальное состояние NoUpdatePending установлено, и ожидание этого НЕ сбрасывает его (таким образом, требование только ручного сброса). Вы не можете войти в обновление, пока какое-либо свойство обновляется. как только вы введете код обновления и очистите событие NoUpdatePending, входящие проп-обновления остановятся и не будут использовать ресурсы семафора. Все запущенные наборы пропусков со временем высвободят ресурсы, необходимые для продолжения обновления.

Все это сказанное, все еще рассматривают параллелизм собственности индивидуально.

3

Другие решения

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

в Update Метод получает все критические разделы, связанные со свойством, перед обновлением. Это приведет к тому, что сеттеры теперь блокируются, если кто-то вызывает их во время обновления.

2

Вот опция, которая использует только критическую секцию и целое число, и не заботится о том, сколько у вас сеттеров:

в каждом сеттере:

  • получить критический раздел csUpdate
  • InterlockedIncrement (&countSettersActive)
  • освободить критическую секцию csUpdate
  • обновить свойство
  • InterlockedDecrement (&countSettersActive)

в основной процедуре обновления:

  • получить критический раздел csUpdate
  • while (InterlockedCompareExchange (&countSettersActive, 0, 0)! = 0) {sleep (1); }
  • сделать обновление
  • освободить критическую секцию csUpdate
0