From 378cfbf96708625e98280c4145d1dbdd9bb009b8 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 10 Jan 2011 01:46:16 +0000 Subject: Working semaphore implementation for OSX. git-svn-id: http://svn.drobilla.net/lad/trunk/raul@2809 a436a847-0d15-0410-975c-d299462d15a1 --- raul.pc.in | 2 +- raul/Semaphore.hpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++-------- wscript | 17 +++++++++++--- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/raul.pc.in b/raul.pc.in index 316ed2c..db1293b 100644 --- a/raul.pc.in +++ b/raul.pc.in @@ -6,5 +6,5 @@ includedir=@includedir@ Name: raul Version: @RAUL_VERSION@ Description: A C++ convenience library for realtime audio applications -Libs: -L${libdir} -lraul @GLIB_LIBS@ @GTHREAD_LIBS@ +Libs: -L${libdir} -lraul @GLIB_LIBS@ @GTHREAD_LIBS@ @RAUL_PC_LIBS@ Cflags: -I${includedir} @GLIB_CFLAGS@ @GTHREAD_CFLAGS@ diff --git a/raul/Semaphore.hpp b/raul/Semaphore.hpp index 6b7d0d7..c7b29ef 100644 --- a/raul/Semaphore.hpp +++ b/raul/Semaphore.hpp @@ -18,30 +18,56 @@ #ifndef RAUL_SEMAPHORE_HPP #define RAUL_SEMAPHORE_HPP +#ifdef __APPLE__ +#include +#include +#else #include +#endif + #include namespace Raul { -/** Trivial wrapper around POSIX semaphores (zero memory overhead). +/** Counting semaphore. * * \ingroup raul */ class Semaphore : boost::noncopyable { public: - inline Semaphore(unsigned int initial) { sem_init(&_sem, 0, initial); } + inline Semaphore(unsigned int initial) { + #ifdef __APPLE__ + MPCreateSemaphore(UINT_MAX, initial, &_sem); + #else + sem_init(&_sem, 0, initial); + #endif + } - inline ~Semaphore() { sem_destroy(&_sem); } + inline ~Semaphore() { + #ifdef __APPLE__ + MPDeleteSemaphore(_sem); + #else + sem_destroy(&_sem); + #endif + } inline void reset(unsigned int initial) { + #ifdef __APPLE__ + MPDeleteSemaphore(_sem); + MPCreateSemaphore(UINT_MAX, initial, &_sem); + #else sem_destroy(&_sem); sem_init(&_sem, 0, initial); + #endif } inline bool has_waiter() { int val; + #ifdef __APPLE__ + #else sem_getvalue(&_sem, &val); + #endif return (val <= 0); } @@ -49,16 +75,29 @@ public: * * Realtime safe. */ - inline void post() { sem_post(&_sem); } + inline void post() { + #ifdef __APPLE__ + MPSignalSemaphore(_sem); + #else + sem_post(&_sem); + #endif + } /** Wait until count is > 0, then decrement. - * - * Note that sem_wait always returns 0 in practice. It returns nonzero - * when run in GDB, so the while is necessary to allow debugging. * * Obviously not realtime safe. */ - inline void wait() { while (sem_wait(&_sem) != 0) {} } + inline void wait() { + #ifdef __APPLE__ + MPWaitOnSemaphore(_sem, kDurationForever); + #else + /* Note that sem_wait always returns 0 in practice, except in + gdb (at least), where it returns nonzero, so the while is + necessary (and is the correct/safe solution in any case). + */ + while (sem_wait(&_sem) != 0) {} + #endif + } /** Non-blocking version of wait(). * @@ -66,10 +105,20 @@ public: * * Realtime safe? */ - inline bool try_wait() { return (sem_trywait(&_sem) == 0); } + inline bool try_wait() { + #ifdef __APPLE__ + return MPWaitOnSemaphore(_sem, kDurationImmediate) == noErr; + #else + return (sem_trywait(&_sem) == 0); + #endif + } private: + #ifdef __APPLE__ + MPSemaphoreID _sem; + #else sem_t _sem; + #endif }; diff --git a/wscript b/wscript index 44c7067..4b2318f 100644 --- a/wscript +++ b/wscript @@ -88,7 +88,10 @@ def build(bld): bld.install_files('${INCLUDEDIR}/raul', bld.path.ant_glob('raul/*.h')) # Pkgconfig file - autowaf.build_pc(bld, 'RAUL', RAUL_VERSION, 'GLIB GTHREAD') + dict = {} + if Options.platform == 'darwin': + dict = {'RAUL_PC_LIBS': '-framework CoreServices'} + autowaf.build_pc(bld, 'RAUL', RAUL_VERSION, 'GLIB GTHREAD', subst_dict=dict) lib_source = ''' src/Configuration.cpp @@ -101,6 +104,11 @@ def build(bld): src/log.cpp ''' + def set_link_flags(obj): + obj.linkflags = [] + if Options.platform == 'darwin': + obj.linkflags = ['-framework', 'CoreServices'] + # Library obj = bld(features = 'cxx cxxshlib') obj.export_includes = ['.'] @@ -111,7 +119,8 @@ def build(bld): obj.uselib = 'GLIB GTHREAD' obj.install_path = '${LIBDIR}' obj.vnum = RAUL_LIB_VERSION - + set_link_flags(obj) + if bld.env['BUILD_TESTS']: # Static library (for unit test code coverage) obj = bld(features = 'cxx cxxstlib') @@ -122,6 +131,7 @@ def build(bld): obj.uselib = 'GLIB GTHREAD' obj.install_path = '' obj.cxxflags = [ '-fprofile-arcs', '-ftest-coverage' ] + set_link_flags(obj) # Unit tests for i in tests.split(): @@ -130,10 +140,11 @@ def build(bld): obj.includes = ['.', './src'] obj.use = 'libraul_static' obj.uselib = 'GLIB GTHREAD' - obj.linkflags = '-lgcov' obj.target = i obj.install_path = '' obj.cxxflags = [ '-fprofile-arcs', '-ftest-coverage' ] + set_link_flags(obj) + obj.linkflags += ['-lgcov'] # Documentation autowaf.build_dox(bld, 'RAUL', RAUL_VERSION, top, out) -- cgit v1.2.1