I'm looking for a way with no side effects.
Ideally, the following code would do the trick:
long currentCount = 0;
::ReleaseSemaphore(h, 0, ¤tCount);
But unfortunately 0 is not allowed as the value of lReleaseCount, so the call returns FALSE.
The sem_getvalue() function retrieves the value of a named or unnamed semaphore. If the current value of the semaphore is zero and there are threads waiting on the semaphore, a negative value is returned. The absolute value of this negative value is the number of threads waiting on the semaphore.
You can check to see if a Semaphore is signaled by calling WaitOne and passing a timeout value of 0 as a parameter. This will cause WaitOne to return immediately with a true or false value indicating whether the semaphore was signaled.
The value of the semaphore S is the number of units of the resource that are currently available. The P operation wastes time or sleeps until a resource protected by the semaphore becomes available, at which time the resource is immediately claimed.
The semaphore object is useful in controlling a shared resource that can support a limited number of users. It acts as a gate that limits the number of threads sharing the resource to a specified maximum number. For example, an application might place a limit on the number of windows that it creates.
If you want that value for external monitoring (as you suggest in your comment) then either use the previous value after a call to ReleaseSemaphore()
or IMHO a better solution is that you implement your own 'interlocked' counter in addition to your semaphore; you then have your monitoring count and can access it in any way you like... Just don't use it as a way of seeing if you can 'enter' the semaphore...
As Chris rightly says, you can't obtain the current count as it is potentially always changing.
This might be a little too late but I think NtQuerySemaphore() is probably what you want to take a look at.
There is no such thing as a "current count" of a Win32 semaphore - which is why you can't get it.
I mean, patently, at some point of time the count on a semaphore will be some value, but from the point of view of a thread, unless it takes action to increase or decrease the semaphore count, another thread might make any answer retrieved entirely invalid the moment it is computed.
It is for this reason that windows api synchronization functions do not let you take the previous lock count without a side effect. The side effect guarantees that you have a valid window of opportunity to actually use the value in a meaningful way.
The obvious "work around" would be to do something like
LONG count = 0;
if( WAIT_OBJECT_0 == WaitForSingleObject(hSemaphore,0L))
{
// Semaphores count is at least one.
ReleaseSemaphore(hSemaphore,1,&count);
}
Why is this better? I'm not sure. But perhaps there is a possibility of doing something meaningful between waiting and releasing that would have been a race condition if ReleaseSemaphore was allowed to release 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With