read-write-store 0.2.0

A concurrent, unordered collection for Rust, where each element has an internally generated ID and a read-write lock.
Documentation
use std::ops::{Deref, DerefMut};
use std::time::Instant;

#[cfg(loom)]
pub struct Park<Inner> {
    inner: Inner,
    lock: loom::sync::Mutex<()>,
    condition: loom::sync::Condvar,
}

#[cfg(loom)]
impl<Inner> Park<Inner> {
    pub fn new(value: Inner) -> Self {
        Self {
            inner: value,
            lock: loom::sync::Mutex::new(()),
            condition: loom::sync::Condvar::new(),
        }
    }

    pub unsafe fn park<T>(
        this: &Self,
        timeout: Option<Instant>,
        f: impl FnOnce() -> ParkChoice<T>,
    ) -> ParkResult<T> {
        debug_assert!(
            timeout.is_none(),
            "cannot park with timeout when using loom"
        );

        let guard = this.lock.lock().unwrap();

        match f() {
            ParkChoice::Park => {
                this.condition.wait(guard).unwrap();
                ParkResult::Waited
            }
            ParkChoice::DontPark(result) => ParkResult::DidntPark(result),
        }
    }

    pub unsafe fn unpark(this: &Self) {
        let _guard = this.lock.lock().unwrap();
        this.condition.notify_all();
    }
}

#[cfg(not(loom))]
pub struct Park<Inner> {
    inner: Inner,
}

#[cfg(not(loom))]
impl<Inner> Park<Inner> {
    pub fn new(value: Inner) -> Self {
        Self { inner: value }
    }

    pub unsafe fn park<T>(
        this: &Self,
        timeout: Option<Instant>,
        f: impl FnOnce() -> ParkChoice<T>,
    ) -> ParkResult<T> {
        use crate::util::debug_check::DebugCheckedMaybeUninit;
        use std::cell::UnsafeCell;
        use std::hint::unreachable_unchecked;

        let addr = this as *const _ as usize;
        let result = UnsafeCell::new(DebugCheckedMaybeUninit::uninit());

        parking_lot::park(
            addr,
            || match f() {
                ParkChoice::Park => {
                    *result.get() = DebugCheckedMaybeUninit::new(ParkResult::Waited);
                    true
                }
                ParkChoice::DontPark(value) => {
                    *result.get() = DebugCheckedMaybeUninit::new(ParkResult::DidntPark(value));
                    false
                }
            },
            || {},
            |_, _| match result.get().read().assume_init() {
                ParkResult::Waited => {
                    *result.get() = DebugCheckedMaybeUninit::new(ParkResult::TimedOut);
                }
                _ => {
                    if cfg!(debug_assertions) {
                        unreachable!()
                    } else {
                        unreachable_unchecked()
                    }
                }
            },
            timeout,
        );

        result.get().read().assume_init()
    }

    pub unsafe fn unpark(this: &Self) {
        let addr = this as *const _ as usize;
        parking_lot::unpark_all(addr);
    }
}

impl<Inner> Deref for Park<Inner> {
    type Target = Inner;

    fn deref(&self) -> &Inner {
        &self.inner
    }
}

impl<Inner> DerefMut for Park<Inner> {
    fn deref_mut(&mut self) -> &mut Inner {
        &mut self.inner
    }
}

pub enum ParkChoice<T> {
    Park,
    DontPark(T),
}

pub enum ParkResult<T> {
    Waited,
    #[allow(unused)]
    TimedOut,
    DidntPark(T),
}