//! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true.
//! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits.

use std::{fmt, hint};

#[derive(Clone, Copy, PartialEq)]
pub enum Mode {
    NoSync,
    Sync,
}

use std::cell::{Cell, UnsafeCell};
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};

use parking_lot::RawMutex;
use parking_lot::lock_api::RawMutex as _;

use crate::sync::{DynSend, DynSync, mode};

/// A guard holding mutable access to a `Lock` which is in a locked state.
#[must_use = "if unused the Lock will immediately unlock"]
pub struct LockGuard<'a, T> {
    lock: &'a Lock<T>,
    marker: PhantomData<&'a mut T>,

    /// The synchronization mode of the lock. This is explicitly passed to let LLVM relate it
    /// to the original lock operation.
    mode: Mode,
}

impl<'a, T: 'a> Deref for LockGuard<'a, T> {
    type Target = T;
    #[inline]
    fn deref(&self) -> &T {
        // SAFETY: We have shared access to the mutable access owned by this type,
        // so we can give out a shared reference.
        unsafe { &*self.lock.data.get() }
    }
}

impl<'a, T: 'a> DerefMut for LockGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        // SAFETY: We have mutable access to the data so we can give out a mutable reference.
        unsafe { &mut *self.lock.data.get() }
    }
}

impl<'a, T: 'a> Drop for LockGuard<'a, T> {
    #[inline]
    fn drop(&mut self) {
        // SAFETY (union access): We get `self.mode` from the lock operation so it is consistent
        // with the `lock.mode` state. This means we access the right union fields.
        match self.mode {
            Mode::NoSync => {
                let cell = unsafe { &self.lock.mode_union.no_sync };
                debug_assert!(cell.get());
                cell.set(false);
            }
            // SAFETY (unlock): We know that the lock is locked as this type is a proof of that.
            Mode::Sync => unsafe { self.lock.mode_union.sync.unlock() },
        }
    }
}

union ModeUnion {
    /// Indicates if the cell is locked. Only used if `Lock.mode` is `NoSync`.
    no_sync: ManuallyDrop<Cell<bool>>,

    /// A lock implementation that's only used if `Lock.mode` is `Sync`.
    sync: ManuallyDrop<RawMutex>,
}

/// The value representing a locked state for the `Cell`.
const LOCKED: bool = true;

/// A lock which only uses synchronization if `might_be_dyn_thread_safe` is true.
/// It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync`.
pub struct Lock<T> {
    /// Indicates if synchronization is used via `mode_union.sync` if it's `Sync`, or if a
    /// not thread safe cell is used via `mode_union.no_sync` if it's `NoSync`.
    /// This is set on initialization and never changed.
    mode: Mode,

    mode_union: ModeUnion,
    data: UnsafeCell<T>,
}

impl<T> Lock<T> {
    #[inline(always)]
    pub fn new(inner: T) -> Self {
        let (mode, mode_union) = if mode::might_be_dyn_thread_safe() {
            hint::cold_path();
            // Create the lock with synchronization enabled using the `RawMutex` type.
            (Mode::Sync, ModeUnion { sync: ManuallyDrop::new(RawMutex::INIT) })
        } else {
            // Create the lock with synchronization disabled.
            (Mode::NoSync, ModeUnion { no_sync: ManuallyDrop::new(Cell::new(!LOCKED)) })
        };
        Lock { mode, mode_union, data: UnsafeCell::new(inner) }
    }

    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.data.into_inner()
    }

    #[inline(always)]
    pub fn get_mut(&mut self) -> &mut T {
        self.data.get_mut()
    }

    #[inline(always)]
    pub fn try_lock(&self) -> Option<LockGuard<'_, T>> {
        let mode = self.mode;
        // SAFETY: This is safe since the union fields are used in accordance with `self.mode`.
        match mode {
            Mode::NoSync => {
                let cell = unsafe { &self.mode_union.no_sync };
                let was_unlocked = cell.get() != LOCKED;
                if was_unlocked {
                    cell.set(LOCKED);
                }
                was_unlocked
            }
            Mode::Sync => unsafe { self.mode_union.sync.try_lock() },
        }
        .then(|| LockGuard { lock: self, marker: PhantomData, mode })
    }

    /// This acquires the lock assuming synchronization is in a specific mode.
    ///
    /// Safety
    /// This method must only be called with `Mode::Sync` if `might_be_dyn_thread_safe` was
    /// true on lock creation.
    #[inline(always)]
    #[track_caller]
    pub unsafe fn lock_assume(&self, mode: Mode) -> LockGuard<'_, T> {
        #[inline(never)]
        #[track_caller]
        #[cold]
        fn lock_held() -> ! {
            panic!("lock was already held")
        }

        // SAFETY: This is safe since the union fields are used in accordance with `mode`
        // which also must match `self.mode` due to the safety precondition.
        unsafe {
            match mode {
                Mode::NoSync => {
                    if self.mode_union.no_sync.replace(LOCKED) == LOCKED {
                        hint::cold_path();
                        lock_held()
                    }
                }
                Mode::Sync => self.mode_union.sync.lock(),
            }
        }
        LockGuard { lock: self, marker: PhantomData, mode }
    }

    #[inline(always)]
    #[track_caller]
    pub fn lock(&self) -> LockGuard<'_, T> {
        unsafe { self.lock_assume(self.mode) }
    }
}

unsafe impl<T: DynSend> DynSend for Lock<T> {}
unsafe impl<T: DynSend> DynSync for Lock<T> {}

impl<T> Lock<T> {
    #[inline(always)]
    #[track_caller]
    pub fn with_lock<F: FnOnce(&mut T) -> R, R>(&self, f: F) -> R {
        f(&mut *self.lock())
    }

    #[inline(always)]
    #[track_caller]
    pub fn borrow(&self) -> LockGuard<'_, T> {
        self.lock()
    }

    #[inline(always)]
    #[track_caller]
    pub fn borrow_mut(&self) -> LockGuard<'_, T> {
        self.lock()
    }
}

impl<T: Default> Default for Lock<T> {
    #[inline]
    fn default() -> Self {
        Lock::new(T::default())
    }
}

impl<T: fmt::Debug> fmt::Debug for Lock<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.try_lock() {
            Some(guard) => f.debug_struct("Lock").field("data", &&*guard).finish(),
            None => {
                struct LockedPlaceholder;
                impl fmt::Debug for LockedPlaceholder {
                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                        f.write_str("<locked>")
                    }
                }

                f.debug_struct("Lock").field("data", &LockedPlaceholder).finish()
            }
        }
    }
}
