Ctrl K
ComunidadGuías…

std/sync.zc

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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();
    }
}