use crate::{AtomicNumber, IntoAtomicNumber};
use atomic_traits::{
fetch::{Add, Max, Min, Sub},
AsPtr, Atomic, Bitwise, NumOps,
};
use core::sync::atomic::Ordering::{self};
use num_primitive::PrimitiveInteger;
use num_traits::FromPrimitive;
pub trait AtomicInteger<N>: Atomic<Type = N> + Bitwise + AsPtr + NumOps
where
N: PrimitiveInteger,
{
}
impl<AI, I> AtomicInteger<I> for AI
where
AI: Atomic<Type = I> + Bitwise + AsPtr + NumOps,
I: PrimitiveInteger,
{
}
pub trait IntoAtomicInteger:
IntoAtomicNumber<AN = Self::AI> + PrimitiveInteger + FromPrimitive
{
type AI: AtomicInteger<Self>;
fn into_atomic_integer(self) -> impl AtomicInteger<Self> {
Self::AI::new(self)
}
}
impl<T, A> IntoAtomicInteger for T
where
T: IntoAtomicNumber<AN = A> + PrimitiveInteger + FromPrimitive,
A: AtomicInteger<Self>,
{
type AI = T::AN;
}
pub trait PrimitiveAtomicInteger: PrimitiveInteger + IntoAtomicInteger {}
impl<T> PrimitiveAtomicInteger for T where T: PrimitiveInteger + IntoAtomicInteger {}
impl<T> NumOps for AtomicNumber<T> where T: PrimitiveAtomicInteger + FromPrimitive {}
impl<T> Add for AtomicNumber<T>
where
T: PrimitiveAtomicInteger + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_add(&self, val: Self::Type, order: Ordering) -> Self::Type {
self.atomic.fetch_add(val, order)
}
}
impl<T> Sub for AtomicNumber<T>
where
T: PrimitiveAtomicInteger + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_sub(&self, val: Self::Type, order: Ordering) -> Self::Type {
self.atomic.fetch_sub(val, order)
}
}
impl<T> Min for AtomicNumber<T>
where
T: PrimitiveAtomicInteger + FromPrimitive,
{
type Type = T;
#[inline(always)]
fn fetch_min(&self, val: Self::Type, order: Ordering) -> Self::Type {
self.atomic.fetch_min(val, order)
}
}
impl<T> Max for AtomicNumber<T>
where
T: PrimitiveAtomicInteger + FromPrimitive,
{
type Type = T;
#[inline]
fn fetch_max(&self, val: Self::Type, order: Ordering) -> T {
self.atomic.fetch_max(val, order)
}
}