Skip to content

Instantly share code, notes, and snippets.

@mattrajca
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattrajca/9538842 to your computer and use it in GitHub Desktop.
Save mattrajca/9538842 to your computer and use it in GitHub Desktop.
An OS X and iOS implementation of semaphores that uses OSAtomic functions (libkern/OSAtomic.h) to guarantee thread safety
//
// main.c
//
// Copyright (c) 2014 Matt Rajca. All rights reserved.
//
#include <stdio.h>
#include <dispatch/dispatch.h>
#include <libkern/OSAtomic.h>
#include <sched.h>
typedef struct _MRSemaphore {
volatile uint32_t lock;
volatile uint32_t sem;
} MRSemaphore;
void MRSemaphoreInit(MRSemaphore *s, uint32_t count) {
s->lock = 0;
s->sem = count;
}
void MRSemaphoreLock(MRSemaphore *s) {
while (1) {
while (OSAtomicTestAndSet(1, &s->lock)) {
sched_yield();
}
if (s->sem > 0) {
// decrement and proceed
s->sem--;
s->lock = 0;
return;
}
// wait
s->lock = 0;
usleep(10);
}
}
void MRSemaphoreUnlock(MRSemaphore *s) {
while (OSAtomicTestAndSet(1, &s->lock)) {
sched_yield();
}
s->sem++;
s->lock = 0;
}
int main(int argc, const char *argv[]) {
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
__block MRSemaphore s;
__block int sharedCounter = 0;
MRSemaphoreInit(&s, 1); // 1 = mutex
for (int n = 0; n < 100000; n++) {
dispatch_async(queue, ^{
MRSemaphoreLock(&s);
sharedCounter++;
MRSemaphoreUnlock(&s);
});
}
dispatch_barrier_sync(queue, ^{
printf("%d (should be 100000)\n", sharedCounter);
});
dispatch_release(queue);
queue = NULL;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment