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 может оставить блокировку мьютекса на семафоре - посмотрите, почему.