DISPATCH_SEMAPHORE_CREATE(3)

πŸ“¦
version 6.2.2 Β· 2 versions
  • 6.2.2 Β· alpine 3.24, arch rolling, epel 10, epel 9, fedora 43, fedora 44, nixos 26.05, opensuse-leap 16.0 (latest)
  • 0~svn197 Β· ubuntu jammy
, in alpine 3.24, arch rolling, epel 10, epel 9, fedora 43, fedora 44, nixos 26.05, opensuse-leap 16.0

✨ NAME ✨

so this page is the Library Functions Manual entry for three besties that always roll together: dispatch_semaphore_create, dispatch_semaphore_signal, and dispatch_semaphore_wait β€” aka the synchronized counting semaphore trio πŸŽ€

(also, tiny heads up: the header at the top of this page spells it dispatch_semaphore_creat(3), missing an e. typo era πŸ’… the footer spells it right. we move on.)


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <dispatch/dispatch.h>

dispatch_semaphore_t
dispatch_semaphore_create(long count);

long
dispatch_semaphore_signal(dispatch_semaphore_t semaphore);

long
dispatch_semaphore_wait(dispatch_semaphore_t semaphore,
    dispatch_time_t timeout);

🌸 DESCRIPTION 🌸

okay so. Dispatch semaphores exist to synchronize threads. that's the whole vibe. 🫢

The dispatch_semaphore_wait() function decrements the semaphore. and if the resulting value is less than zero?? it waits β€” like, actually blocks β€” for a signal from a thread that increments the semaphore by calling dispatch_semaphore_signal(), and only then does it return. ✨ the timeout param is creatable with the dispatch_time(3) or dispatch_walltime(3) functions. and if that timeout gets reached without a signal ever showing up, the semaphore gets re-incremented before the function returns β€” so it's not just leaving you on read, it puts the count back. 😌

The dispatch_semaphore_signal() function increments the counting semaphore. and if the previous value was less than zero, it wakes one of the threads that are waiting in dispatch_semaphore_wait() before returning. one. not all of them. just one. πŸ‘‘


πŸŽ€ COMPLETION SYNCHRONIZATION πŸŽ€

if the count parameter equals zero, then the semaphore is the move for synchronizing completion of work. like, "don't do the thing until the other thing is done" energy. for example:

sema = dispatch_semaphore_create(0);

dispatch_async(queue, ^{
        foo();
        dispatch_semaphore_signal(sema);
});

bar();

dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

🧚 FINITE RESOURCE POOL 🧚

if the count parameter is greater than zero, then the semaphore is the move for managing a finite pool of resources. no cap. for example, a library that wants to limit Unix descriptor usage:

sema = dispatch_semaphore_create(getdtablesize() / 4);

at each Unix FD allocation:

dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
fd = open("/etc/services", O_RDONLY);

when each FD is closed:

close(fd);
dispatch_semaphore_signal(sema);

see how it's giving... balanced?? that's the whole point bestie 🌈


⭐ RETURN VALUES ⭐

  • The dispatch_semaphore_create() function returns NULL if no memory is available, or if the count parameter is less than zero. (yeah, negative counts are not it. πŸ’€)
  • The dispatch_semaphore_signal() function returns non-zero when a thread is woken. otherwise, zero is returned.
  • The dispatch_semaphore_wait() function returns zero upon success and non-zero after the timeout expires. and if the timeout is DISPATCH_TIME_FOREVER, then dispatch_semaphore_wait() waits forever and always returns zero.

πŸ’œ MEMORY MODEL πŸ’œ

Dispatch semaphores are retained and released via calls to dispatch_retain() and dispatch_release(). that's the memory model, periodt. 🫑


πŸ’€ CAVEATS πŸ’€

⚠️ Unbalanced dispatch semaphores cannot be released. for a given semaphore, calls to dispatch_semaphore_signal() and dispatch_semaphore_wait() must be balanced before dispatch_release() is called on it.

like, don't be out here signaling more than you wait or waiting more than you signal and then trying to release. that's a no. balance your semaphores or suffer the consequences, bestie 😭


πŸ‘‘ SEE ALSO πŸ‘‘


and that's the page!! 🌟 this one's from Darwin, dated May 1, 2009, and it's the man page for dispatch_semaphore_create(3) β€” go forth and synchronize responsibly, you absolute icon 🫢✨