import "./core.zc" import "./mem.zc" include include struct Mutex { handle: void*; } impl Mutex { /// Creates a new Mutex. fn new() -> Mutex { let ptr = alloc_bytes(64); pthread_mutex_init((pthread_mutex_t*)ptr, NULL); return Mutex { handle: ptr }; } /// Locks the mutex. fn lock(self) { pthread_mutex_lock((pthread_mutex_t*)self.handle); } /// Unlocks the mutex. fn unlock(self) { pthread_mutex_unlock((pthread_mutex_t*)self.handle); } fn try_lock(self) -> bool { return pthread_mutex_trylock((pthread_mutex_t*)self.handle) == 0; } fn free(self) { if (self.handle != NULL) { pthread_mutex_destroy((pthread_mutex_t*)self.handle); dealloc(self.handle); self.handle = NULL; } } } struct CondVar { handle: void*; } impl CondVar { /// Creates a new Mutex. fn new() -> CondVar { let ptr = alloc_bytes(64); pthread_cond_init((pthread_cond_t*)ptr, NULL); return CondVar { handle: ptr }; } fn wait(self, mutex: Mutex*) { pthread_cond_wait((pthread_cond_t*)self.handle, (pthread_mutex_t*)(*mutex).handle); } fn signal(self) { pthread_cond_signal((pthread_cond_t*)self.handle); } fn broadcast(self) { pthread_cond_broadcast((pthread_cond_t*)self.handle); } fn free(self) { if (self.handle != NULL) { pthread_cond_destroy((pthread_cond_t*)self.handle); dealloc(self.handle); self.handle = NULL; } } } struct RwLock { handle: void*; } impl RwLock { /// Creates a new Mutex. fn new() -> RwLock { let ptr = alloc_bytes(64); pthread_rwlock_init((pthread_rwlock_t*)ptr, NULL); return RwLock { handle: ptr }; } fn rdlock(self) { pthread_rwlock_rdlock((pthread_rwlock_t*)self.handle); } fn wrlock(self) { pthread_rwlock_wrlock((pthread_rwlock_t*)self.handle); } /// Unlocks the mutex. fn unlock(self) { pthread_rwlock_unlock((pthread_rwlock_t*)self.handle); } fn try_rdlock(self) -> bool { return pthread_rwlock_tryrdlock((pthread_rwlock_t*)self.handle) == 0; } fn try_wrlock(self) -> bool { return pthread_rwlock_trywrlock((pthread_rwlock_t*)self.handle) == 0; } fn free(self) { if (self.handle != NULL) { pthread_rwlock_destroy((pthread_rwlock_t*)self.handle); dealloc(self.handle); self.handle = NULL; } } } impl Drop for Mutex { fn drop(self) { self.free(); } } impl Drop for CondVar { fn drop(self) { self.free(); } } impl Drop for RwLock { fn drop(self) { self.free(); } } struct Once { mutex: Mutex; done: bool; } impl Once { /// Creates a new Mutex. fn new() -> Once { return Once { mutex: Mutex::new(), done: false }; } /// Runs the closure while holding the lock. fn call(self, func: fn()) { if (self.done) return; self.mutex.lock(); if (!self.done) { func(); self.done = true; } self.mutex.unlock(); } fn free(self) { self.mutex.free(); } } struct Barrier { handle: void*; } @cfg(apple) struct BarrierData { mutex: Mutex; cond: CondVar; count: int; threshold: int; generation: int; } impl Barrier { @cfg(apple) /// Creates a new Mutex. fn new(count: int) -> Barrier { let data = (BarrierData*)alloc_bytes(sizeof(BarrierData)); data.mutex = Mutex::new(); data.cond = CondVar::new(); data.count = count; data.threshold = count; data.generation = 0; return Barrier { handle: data }; } @cfg(not(apple)) /// Creates a new Mutex. fn new(count: int) -> Barrier { let ptr = alloc_bytes(64); pthread_barrier_init((pthread_barrier_t*)ptr, NULL, count); return Barrier { handle: ptr }; } @cfg(apple) fn wait(self) -> bool { let data = (BarrierData*)self.handle; data.mutex.lock(); let gen = data.generation; data.count = data.count - 1; if (data.count == 0) { data.generation = data.generation + 1; data.count = data.threshold; data.cond.broadcast(); data.mutex.unlock(); return true; } while (gen == data.generation) { data.cond.wait(&data.mutex); } data.mutex.unlock(); return false; } @cfg(not(apple)) fn wait(self) -> bool { let ret = pthread_barrier_wait((pthread_barrier_t*)self.handle); if (ret == 0 || ret == -1) { return true; } return false; } @cfg(apple) fn free(self) { if (self.handle != NULL) { let data = (BarrierData*)self.handle; data.mutex.free(); data.cond.free(); dealloc(data); self.handle = NULL; } } @cfg(not(apple)) fn free(self) { if (self.handle != NULL) { pthread_barrier_destroy((pthread_barrier_t*)self.handle); dealloc(self.handle); self.handle = NULL; } } } impl Drop for Barrier { fn drop(self) { self.free(); } } struct Semaphore { handle: void*; } @cfg(apple) struct SemData { mutex: Mutex; cond: CondVar; count: int; } impl Semaphore { @cfg(apple) /// Creates a new Mutex. fn new(value: int) -> Semaphore { let data = (SemData*)zalloc_bytes(sizeof(SemData)); data.mutex = Mutex::new(); data.cond = CondVar::new(); data.count = value; return Semaphore { handle: data }; } @cfg(not(apple)) /// Creates a new Mutex. fn new(value: int) -> Semaphore { let ptr = alloc_bytes(32); sem_init((sem_t*)ptr, 0, value); return Semaphore { handle: ptr }; } @cfg(apple) fn wait(self) { let data = (SemData*)self.handle; data.mutex.lock(); while (data.count <= 0) { data.cond.wait(&data.mutex); } data.count = data.count - 1; data.mutex.unlock(); } @cfg(not(apple)) fn wait(self) { sem_wait((sem_t*)self.handle); } @cfg(apple) fn try_wait(self) -> bool { let data = (SemData*)self.handle; data.mutex.lock(); if (data.count > 0) { data.count = data.count - 1; data.mutex.unlock(); return true; } data.mutex.unlock(); return false; } @cfg(not(apple)) fn try_wait(self) -> bool { return sem_trywait((sem_t*)self.handle) == 0; } @cfg(apple) fn post(self) { let data = (SemData*)self.handle; data.mutex.lock(); data.count = data.count + 1; data.cond.signal(); data.mutex.unlock(); } @cfg(not(apple)) fn post(self) { sem_post((sem_t*)self.handle); } @cfg(apple) fn value(self) -> int { let data = (SemData*)self.handle; data.mutex.lock(); let val = data.count; data.mutex.unlock(); return val; } @cfg(not(apple)) fn value(self) -> int { let val: int = 0; sem_getvalue((sem_t*)self.handle, &val); return val; } @cfg(apple) fn free(self) { if (self.handle != NULL) { let data = (SemData*)self.handle; data.mutex.free(); data.cond.free(); dealloc(data); self.handle = NULL; } } @cfg(not(apple)) fn free(self) { if (self.handle != NULL) { sem_destroy((sem_t*)self.handle); dealloc(self.handle); self.handle = NULL; } } } impl Drop for Once { fn drop(self) { self.free(); } } impl Drop for Semaphore { fn drop(self) { self.free(); } }