copy-channels 1.0.0

A collection of cross-thread channels for copyable types
Documentation
//! Implements channels for types that are "natively" atomic, i.e. most primitives.

use crate::loom::sync::atomic::Ordering;
use crate::loom::sync::atomic::*;
use std::mem::MaybeUninit;

pub trait NativelyAtomic {
    type Atomic: Default;

    fn read(slot: &Self::Atomic, ordering: Ordering) -> Self;
    fn write(self, slot: &Self::Atomic, ordering: Ordering);
}

macro_rules! impl_for {
    ($n:ty, $a:ty) => {
        impl NativelyAtomic for $n {
            type Atomic = $a;

            #[inline]
            fn read(slot: &Self::Atomic, ordering: Ordering) -> Self {
                slot.load(ordering)
            }

            #[inline]
            fn write(self, slot: &Self::Atomic, ordering: Ordering) {
                slot.store(self, ordering);
            }
        }
    };
}

impl_for!(u8, AtomicU8);
impl_for!(u16, AtomicU16);
impl_for!(u32, AtomicU32);
impl_for!(u64, AtomicU64);
impl_for!(usize, AtomicUsize);
impl_for!(i8, AtomicI8);
impl_for!(i16, AtomicI16);
impl_for!(i32, AtomicI32);
impl_for!(i64, AtomicI64);
impl_for!(isize, AtomicIsize);
impl_for!(bool, AtomicBool);

impl<T> NativelyAtomic for *mut T {
    type Atomic = AtomicPtr<T>;

    #[inline]
    fn read(slot: &Self::Atomic, ordering: Ordering) -> Self {
        slot.load(ordering)
    }
    #[inline]
    fn write(self, slot: &Self::Atomic, ordering: Ordering) {
        slot.store(self, ordering);
    }
}

impl NativelyAtomic for () {
    type Atomic = ();

    #[inline]
    fn read(_slot: &Self::Atomic, _ordering: Ordering) -> Self {}
    #[inline]
    fn write(self, _slot: &Self::Atomic, _ordering: Ordering) {}
}

pub struct NativeSlotable;

impl<T: NativelyAtomic> super::Slotable<T> for NativeSlotable {
    type Slot = T::Atomic;
    type SlotArrayItem = T::Atomic;

    fn boxed_uninit_single() -> Box<Self::Slot> {
        Box::new(T::Atomic::default())
    }

    fn read(slot: &Self::Slot, ordering: Ordering) -> MaybeUninit<T> {
        MaybeUninit::new(T::read(slot, ordering))
    }

    fn write(slot: &Self::Slot, value: T, ordering: Ordering) {
        value.write(slot, ordering);
    }

    fn boxed_uninit_multiple(n: usize) -> Box<[Self::SlotArrayItem]> {
        std::iter::repeat_with(T::Atomic::default)
            .take(n)
            .collect::<Vec<_>>()
            .into_boxed_slice()
    }

    fn index_in_array(items: &[Self::SlotArrayItem], index: usize) -> &Self::Slot {
        &items[index]
    }
}

crate::impl_channels!(crate::native::NativeSlotable, crate::native::NativelyAtomic);