std/sync.zc
Rama main · réplica de lectura del repositorio original.
import "./core.zc"
import "./mem.zc"
include <pthread.h>
include <semaphore.h>
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<void>(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<void>(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<void>(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<BarrierData>(data);
self.handle = NULL;
}
}
@cfg(not(apple))
fn free(self) {
if (self.handle != NULL) {
pthread_barrier_destroy((pthread_barrier_t*)self.handle);
dealloc<void>(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<SemData>(data);
self.handle = NULL;
}
}
@cfg(not(apple))
fn free(self) {
if (self.handle != NULL) {
sem_destroy((sem_t*)self.handle);
dealloc<void>(self.handle);
self.handle = NULL;
}
}
}
impl Drop for Once {
fn drop(self) {
self.free();
}
}
impl Drop for Semaphore {
fn drop(self) {
self.free();
}
}