// As macro: PTHREAD_ONCE_INIT

use core::sync::atomic::Ordering;

use crate::{error::CIntZeroResult, headers::sys_types::pthread_once_t, util::PointerExt};

impl pthread_once_t {
    fn once(&self, constructor: extern "C" fn()) {
        if self
            .__state
            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
            .is_err()
        {
            return;
        }
        constructor();
    }
}

#[no_mangle]
unsafe extern "C" fn pthread_once(
    once: *mut pthread_once_t,
    constructor: extern "C" fn(),
) -> CIntZeroResult {
    let once = once.ensure_mut();
    assert_ne!(constructor as usize, 0);

    once.once(constructor);

    CIntZeroResult::SUCCESS
}
