How to know DispatchSemaphore's current count?

Wait() and Signal() would be used to decrement and increment semaphore count. But how to know semaphore's current count?

    let semaphore = DispatchSemaphore(value: 3)
    var name = "Vishwanath"
    

    /* 
       How to apply check condition here:
       if semaphore count is less than or equal to 3, then only proceed else print saying no recourse available currently and return
     
        guard semaphore.count <= 3 else { 
          print("No resource available") 
          return
       }
    */

    semaphore.wait()
    name = "Vish Deshmukh"
    semaphore.signal()

There's no way to check, but you can wait with zero-second timeout multiple times.

There’s no API for this because it is an inherently racy condition. As soon as you check, your thread could be interrupted and other threads can increment or decrement the semaphore.

1 Like

I tried with following but it executes timeout quickly for first 3 statements and returns. Only fourth check work so I am not sure how to use it correctly.

if semaphore.wait(timeout: .now()) == .success {
print("ERROR")
return
}

Counting semaphores are designed so that wait succeeds if it can decrement and still leave the count non-negative. That's just how they work; there is no way to have wait instead succeed only if the count would be <= 3. To use them, you have to find a way to fit your problem around that constraint. If you can't find a way to do that, then you will need to fall back on the more general technique of using a lock and (possibly) a condition variable.

With that said, though, as a general rule, you should try to avoid condition variables and semaphores, because they are susceptible to unavoidable priority inversions. They're only really acceptable if you're always using a zero timeout and so will never block, but if you're doing that, you don't need a semaphore in the first place and can just use a simple atomic.

6 Likes

Thank you!