Я ищу путь без побочных эффектов.
Идеально, следующий код добился бы цели:
long currentCount = 0;
::ReleaseSemaphore(h, 0, ¤tCount);
Но к сожалению 0 не позволяется как значение lReleaseCount, таким образом, вызов возвращает FALSE.
Если вам нужно это значение для внешнего мониторинга (как вы предлагаете в своем комментарии), то либо используйте предыдущее значение после вызова ReleaseSemaphore()
, либо, IMHO, лучшим решением является реализация собственного "взаимосвязанного" счетчика в дополнение к вашему семафору; тогда у вас будет свой счетчик мониторинга и вы сможете обращаться к нему любым способом... Только не используйте его как способ проверить, можете ли вы "войти" в семафор...
Как правильно сказал Крис, вы не можете получить текущий счетчик, поскольку он потенциально всегда меняется.
Не существует такого понятия, как «текущий подсчет» семафора Win32 - вот почему вы не можете его получить.
Я имею в виду, очевидно, что в какой-то момент времени количество семафора будет некоторым значением, но с точки зрения потока, если он не предпринимает действий по увеличению или уменьшению количества семафоров, другой поток может сделать любой ответ, полученный полностью недействительным в момент его вычисления.
Именно по этой причине функции синхронизации Windows API не позволяют вам взять предыдущее количество блокировок без побочного эффекта. Побочный эффект гарантирует, что у вас есть действительное окно возможностей для реального использования значения значимым образом.
Очевидным «обходом» было бы сделать что-то вроде
LONG count = 0;
if( WAIT_OBJECT_0 == WaitForSingleObject(hSemaphore,0L))
{
// Semaphores count is at least one.
ReleaseSemaphore(hSemaphore,1,&count);
}
Почему это лучше? Я не уверен. Но, возможно, есть возможность сделать что-то значимое между ожиданием и выпуском, что было бы условием гонки, если бы ReleaseSemaphore было разрешено выпустить 0.