Question

Does iOS have any kind of very low level condition lock that does not include locking?

I am looking for a way to signal an awaiting thread from within the Core Audio render thread, without the usage of locks. I was wondering if something low level as a Mach system call might exist.

Right now I have a Core Audio thread that uses a non-blocking thread safe message queue to send messages to another thread. The other thread then pulls every 100ms to see if messages are available in the queue.

But this is very rudimentary and the timing is awful. I could use condition locks, but that involves locking, and I would like to keep any kind of locking out of the rendering thread.

What I am looking for is having the message queue thread wait until the Core Audio render thread signals it. Just like pthread conditions, but without locking and without immediate context switching? I would like the Core Audio thread to complete before the message queue thread is woken up.

Was it helpful?

Solution

Updated

A dispatch_semaphore_t works well and is more efficient than a mach semaphore_t. The original code looks like this using a dispatch semaphore:

#include <dispatch/dispatch.h>

// Declare mSemaphore somewhere it is available to multiple threads
dispatch_semaphore_t mSemaphore;


// Create the semaphore
mSemaphore = dispatch_semaphore_create(0);
// Handle error if(nullptr == mSemaphore)


// ===== RENDER THREAD
// An event happens in the render thread- set a flag and signal whoever is waiting
/*long result =*/ dispatch_semaphore_signal(mSemaphore);


// ===== OTHER THREAD
// Check the flags and act on the state change
// Wait for a signal for 2 seconds
/*long result =*/ dispatch_semaphore_wait(mSemaphore, dispatch_time(dispatch_time_now(), 2 * NSEC_PER_SEC));


// Clean up when finished
dispatch_release(mSemaphore);

Original answer:

You can use a mach semaphore_t for this purpose. I've written a C++ class that encapsulates the functionality: https://github.com/sbooth/SFBAudioEngine/blob/master/Semaphore.cpp

Whether or not you end up using my wrapper or rolling your own the code will look roughly like:

#include <mach/mach.h>
#include <mach/task.h>

// Declare mSemaphore somewhere it is available to multiple threads
semaphore_t mSemaphore;


// Create the semaphore
kern_return_t result = semaphore_create(mach_task_self(), &mSemaphore, SYNC_POLICY_FIFO, 0);
// Handle error if(result != KERN_SUCCESS)


// ===== RENDER THREAD
// An event happens in the render thread- set a flag and signal whoever is waiting
kern_return_t result = semaphore_signal(mSemaphore);
// Handle error if(result != KERN_SUCCESS)


// ===== OTHER THREAD
// Check the flags and act on the state change
// Wait for a signal for 2 seconds
mach_timespec_t duration = {
  .tv_sec = 2,
  .tv_nsec = 0
};

kern_return_t result = semaphore_timedwait(mSemaphore, duration);

// Timed out
if(KERN_OPERATION_TIMED_OUT != result)
  ;

// Handle error if(result != KERN_SUCCESS)


// Clean up when finished
kern_return_t result = semaphore_destroy(mach_task_self(), mSemaphore);
// Handle error if(result != KERN_SUCCESS)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top