pthread-win32 расширение sem_post_multiple

В настоящее время я создаю тонкую оболочку C++ вокруг pthreads для внутреннего использования. Windows и QNX нацелены, и, к счастью, порты pthreads-win32, кажется, работают очень хорошо, в то время как QNX совместим с POSIX для наших практических целей.

Теперь, реализуя семафоры, я нажал на функцию

sem_post_multiple(sem_t*, int)

который, по-видимому, доступен только на pthreads-win32, но отсутствует в QNX. Как следует из названия, функция должна увеличивать семафор на число, указанное в качестве второго аргумента. Насколько я могу судить, функция не является частью ни POSIX 1b, ни POSIX 1c.

Хотя в настоящее время нет никаких требований к указанной функции, я все еще задаюсь вопросом, почему pthreads-win32 предоставляет функцию и может ли она быть полезной. Я мог бы попытаться имитировать его для QNX, используя примерно следующее:

sem_post_multiple_qnx(sem_t* sem, int count)
{
   for(;count > 0; --count)
   {
       sem_post(sem);
   }
} 

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

Заранее спасибо.

PS: я намеренно пропустил свой модный класс C++ для ясности. Для всех людей, предлагающих помощь для спасения: это не вариант в моем текущем проекте по причинам управления.

4 ответа

Решение

В любом случае семафоры являются необязательным расширением в POSIX. Например, OS X, кажется, не реализует их полностью. Так что, если вы обеспокоены переносимостью, вам все равно придется предоставить обертки необходимых вам функций.

Ваш подход к эмуляции атомарного приращения повторяется sem_post конечно есть минусы.

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

Я бы придерживался только необходимого, строго соответствующего POSIX. Остерегайтесь этого sem_timedwait еще одна необязательная часть опции семафора.

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

Лично я хотел бы оставить их обоих в покое: попытка добавить фундаментальные операции синхронизации в систему, в которой их нет, - игра в кружку, и ваша обертка может вскоре перестать быть "тонкой". Так что не входите в это, если у вас нет кода, который использует sem_post_multiple, что вам абсолютно необходимо портировать.

sem_post_multiple() - это нестандартная вспомогательная функция, представленная сопровождающими win32-pthreads. Ваша реализация отличается от их реализации, потому что множественные декременты не являются атомарными. Является ли это проблемой, зависит от предполагаемого использования. (Лично я не буду пытаться реализовать эту функцию, если / пока не возникнет необходимость.)

Это интересный вопрос. +1.

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

  • Начать поток A, который вызывает sem_post_multiple( s, 10)
  • Поток B, ожидающий на s, освобожден. Нить B убивает нить A.

В приведенном выше недружественном сценарии атомарная версия увеличила бы семафор на 10. В неатомарной версии его можно увеличить только один раз. Этот пример, конечно, вряд ли в реальном мире. Например, уничтожение потока - почти всегда плохая идея, не говоря уже о том, что он может оставить объект семафора в недопустимом состоянии. Реализация Win32 может оставить блокировку мьютекса на семафоре - посмотрите, почему.

Другие вопросы по тегам