hipthread 0.1.3

no-std thread library based on pthread
Documentation
use super::pthread;
use core::mem::MaybeUninit;
use hierr::{Error, Result};

/// 封装sem_t
pub struct Semaphore {
    sem: MaybeUninit<pthread::sem_t>,
}

unsafe impl Send for Semaphore {}
unsafe impl Sync for Semaphore {}

impl Drop for Semaphore {
    fn drop(&mut self) {
        unsafe { pthread::sem_destroy(self.sem.as_mut_ptr()) };
    }
}

impl Semaphore {
    pub fn new(init_value: u32) -> Result<Self> {
        let this = Self {
            sem: MaybeUninit::uninit(),
        };
        let ret = unsafe { pthread::sem_init(this.get_sem(), 0, init_value as pthread::c_uint) };
        if ret == 0 {
            Ok(this)
        } else {
            Err(Error::last())
        }
    }

    pub fn post(&self) {
        unsafe { pthread::sem_post(self.get_sem()) };
    }

    pub fn wait(&self) {
        unsafe { pthread::sem_wait(self.get_sem()) };
    }

    fn get_sem(&self) -> *mut pthread::sem_t {
        self.sem.as_ptr().cast_mut()
    }
}

#[cfg(test)]
mod test {
    use crate::*;
    use core::sync::atomic::Ordering::*;
    use core::sync::atomic::*;
    use hipool::*;

    #[test]
    fn test_semaphore() {
        let sem = Arc::new(Semaphore::new(0).unwrap()).unwrap();
        let cloned = sem.clone();
        static GVALUE: AtomicI32 = AtomicI32::new(0);
        let _ = spawn_with(
            move || {
                let _ = GVALUE.fetch_add(1, Relaxed);
                cloned.post();
            },
            &ThrdAttr::new().set_detachstate(true),
        )
        .unwrap();
        sem.wait();
        assert_eq!(GVALUE.load(Relaxed), 1);
    }
}