dispatch_semaphore_create(3)
DESCRIPTION
Dispatch semaphores are used to synchronize threads. The timeout parameter is creatable with the dispatch_time(3) or dispatch_walltime(3) functions.
COMPLETION SYNCHRONIZATION
- If the count parameter is equal to zero, then the semaphore is useful for
synchronizing completion of work. 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 useful
for managing a finite pool of resources. 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);
RETURN VALUES
The dispatch_semaphore_create() function returns NULL if no memory is
available or if the count parameter is less than zero.
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 nonzero after the timeout expires. 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().
CAVEATS
Dispatch semaphores are strict counting semaphores. In other words, dispatch semaphores do not saturate at any particular value. Saturation can
be achieved through atomic compare-and-swap logic. What follows is a
saturating binary semaphore:
- void
saturating_semaphore_signal(dispatch_semaphore_t dsema, int *sent)
{ - if (__sync_bool_compare_and_swap(sent, 0, 1)) {
dispatch_semaphore_signal(dsema);
- }
- }
- void
saturating_semaphore_wait(dispatch_semaphore_t dsema, int *sent)
{ - *sent = 0;
dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER); - }