From 7b2b7c64cca7a0e8043c7c7c52b1f38c4d589246 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 15 Feb 2024 16:14:03 +0100 Subject: [PATCH] . --- rtic-sync/src/bit_channel.rs | 74 ++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/rtic-sync/src/bit_channel.rs b/rtic-sync/src/bit_channel.rs index 703d351a64..bd436d1658 100644 --- a/rtic-sync/src/bit_channel.rs +++ b/rtic-sync/src/bit_channel.rs @@ -2,11 +2,9 @@ use bitflags::{Bits, Flags}; use core::sync::atomic::{AtomicU16, AtomicU8, Ordering}; +use portable_atomic::{AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicU32, AtomicU64}; -// -// Bit channel -// - +/// A channel for setting and clearing `bitflags` concurrently. pub struct BitChannel where T: Flags, @@ -20,44 +18,73 @@ where T: Flags, T::Bits: AtomicType, { + /// Create a new `bitflags` channel. pub const fn new() -> Self { BitChannel { atomic: T::Bits::ATOMIC_ZERO, } } - pub fn test(&self) { - T::Bits::fetch_and(&self.atomic, T::Bits::EMPTY, Ordering::Relaxed); + /// Set `bitflag`s. + #[inline] + pub fn send(&self, flags: T) { + T::Bits::fetch_or(&self.atomic, flags.bits(), Ordering::Relaxed); + } + + /// Receive the current value of the `bitflags` and reset all flags. + #[inline] + pub fn recv(&self) -> T { + ::from_bits_retain(T::Bits::fetch_and( + &self.atomic, + T::Bits::EMPTY, + Ordering::Relaxed, + )) } } +/// Generic atomic trait, allows for taking any `bitflags::Bits` as an atomic. pub trait AtomicType: Sized { + /// The underlying atomic, e.g. `AtomicU8`, `AtomicU16`. type Atomic: From; - + + /// The definition of that atomic with value 0. const ATOMIC_ZERO: Self::Atomic; + /// The atomic's `fetch_and` implementation forwarded. fn fetch_and(a: &Self::Atomic, b: Self, order: Ordering) -> Self; + + /// The atomic's `fetch_or` implementation forwarded. + fn fetch_or(a: &Self::Atomic, b: Self, order: Ordering) -> Self; } -impl AtomicType for u16 { - type Atomic = AtomicU16; - - const ATOMIC_ZERO: Self::Atomic = AtomicU16::new(0); +macro_rules! atomic_type_impl { + ($atomic:ty, $integer:ty) => { + impl AtomicType for $integer { + type Atomic = $atomic; - fn fetch_and(a: &Self::Atomic, b: Self, order: Ordering) -> Self { - a.fetch_and(b, order) - } + const ATOMIC_ZERO: Self::Atomic = <$atomic>::new(0); + + #[inline(always)] + fn fetch_and(a: &Self::Atomic, b: Self, order: Ordering) -> Self { + a.fetch_and(b, order) + } + + #[inline(always)] + fn fetch_or(a: &Self::Atomic, b: Self, order: Ordering) -> Self { + a.fetch_or(b, order) + } + } + }; } -impl AtomicType for u8 { - type Atomic = AtomicU8; - - const ATOMIC_ZERO: Self::Atomic = AtomicU8::new(0); - - fn fetch_and(a: &Self::Atomic, b: Self, order: Ordering) -> Self { - a.fetch_and(b, order) - } -} +atomic_type_impl!(AtomicU8, u8); +atomic_type_impl!(AtomicU16, u16); +atomic_type_impl!(AtomicU32, u32); +atomic_type_impl!(AtomicU64, u64); +atomic_type_impl!(AtomicI8, i8); +atomic_type_impl!(AtomicI16, i16); +atomic_type_impl!(AtomicI32, i32); +atomic_type_impl!(AtomicI64, i64); // etc... @@ -86,4 +113,3 @@ mod tests { let b = BitChannel::::new(); } } -