#![forbid(unsafe_op_in_unsafe_fn)]

use crate::pin::Pin;
use crate::ptr;
use crate::sync::atomic::Ordering::Relaxed;
use crate::sync::atomic::{Atomic, AtomicUsize};
use crate::sys::pal::sync as pal;
use crate::sys::sync::{Mutex, OnceBox};
use crate::time::{Duration, Instant};

pub struct Condvar {
    cvar: OnceBox<pal::Condvar>,
    mutex: Atomic<usize>,
}

impl Condvar {
    pub const fn new() -> Condvar {
        Condvar { cvar: OnceBox::new(), mutex: AtomicUsize::new(0) }
    }

    #[inline]
    fn get(&self) -> Pin<&pal::Condvar> {
        self.cvar.get_or_init(|| {
            let mut cvar = Box::pin(pal::Condvar::new());
            // SAFETY: we only call `init` once per `pal::Condvar`, namely here.
            unsafe { cvar.as_mut().init() };
            cvar
        })
    }

    #[inline]
    fn verify(&self, mutex: Pin<&pal::Mutex>) {
        let addr = ptr::from_ref::<pal::Mutex>(&mutex).addr();
        // Relaxed is okay here because we never read through `self.mutex`, and only use it to
        // compare addresses.
        match self.mutex.compare_exchange(0, addr, Relaxed, Relaxed) {
            Ok(_) => {}               // Stored the address
            Err(n) if n == addr => {} // Lost a race to store the same address
            _ => panic!("attempted to use a condition variable with two mutexes"),
        }
    }

    #[inline]
    pub fn notify_one(&self) {
        // SAFETY: we called `init` above.
        unsafe { self.get().notify_one() }
    }

    #[inline]
    pub fn notify_all(&self) {
        // SAFETY: we called `init` above.
        unsafe { self.get().notify_all() }
    }

    #[inline]
    pub unsafe fn wait(&self, mutex: &Mutex) {
        // SAFETY: the caller guarantees that the lock is owned, thus the mutex
        // must have been initialized already.
        let mutex = unsafe { mutex.pal.get_unchecked() };
        self.verify(mutex);
        // SAFETY: we called `init` above, we verified that this condition
        // variable is only used with `mutex` and the caller guarantees that
        // `mutex` is locked by the current thread.
        unsafe { self.get().wait(mutex) }
    }

    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
        // SAFETY: the caller guarantees that the lock is owned, thus the mutex
        // must have been initialized already.
        let mutex = unsafe { mutex.pal.get_unchecked() };
        self.verify(mutex);

        if pal::Condvar::PRECISE_TIMEOUT {
            // SAFETY: we called `init` above, we verified that this condition
            // variable is only used with `mutex` and the caller guarantees that
            // `mutex` is locked by the current thread.
            unsafe { self.get().wait_timeout(mutex, dur) }
        } else {
            // Timeout reports are not reliable, so do the check ourselves.
            let now = Instant::now();
            // SAFETY: we called `init` above, we verified that this condition
            // variable is only used with `mutex` and the caller guarantees that
            // `mutex` is locked by the current thread.
            let woken = unsafe { self.get().wait_timeout(mutex, dur) };
            woken || now.elapsed() < dur
        }
    }
}
