r3_core 0.1.4

R3-OS API definition
Documentation
//! Event groups
use core::{fmt, hash};

use super::{
    raw, raw_cfg, Cfg, GetEventGroupError, PollEventGroupError, UpdateEventGroupError,
    WaitEventGroupError, WaitEventGroupTimeoutError,
};
use crate::time::Duration;

pub use raw::{EventGroupBits, EventGroupWaitFlags};

// ----------------------------------------------------------------------------

define_object! {
/// Represents a single owned event group in a system.
///
#[doc = common_doc_owned_handle!()]
///
/// An event group is a set of bits that can be updated and waited for to be
/// set.
///
/// <div class="admonition-follows"></div>
///
/// > **Relation to Other Specifications:**
/// > event group (FreeRTOS), event group (Freescale MQX), `EventFlags` (Mbed
/// > OS), events (OSEK/VDX, assigned to each extended task), event (RT-Thread),
/// > event set (RTEMS, assigned to each task), Eventflag (μITRON4.0)
#[doc = include_str!("../common.md")]
pub struct EventGroup<System: _>(System::RawEventGroupId);

/// Represents a single borrowed event group in a system.
#[doc = include_str!("../common.md")]
pub struct EventGroupRef<System: raw::KernelEventGroup>(_);

pub type StaticEventGroup<System>;

pub trait EventGroupHandle {}
pub trait EventGroupMethods {}
}

impl<System: raw::KernelEventGroup> StaticEventGroup<System> {
    /// Construct a `EventGroupDefiner` to define an event group in [a
    /// configuration function](crate#static-configuration).
    pub const fn define() -> EventGroupDefiner<System> {
        EventGroupDefiner::new()
    }
}

/// The supported operations on [`EventGroupHandle`].
#[doc = include_str!("../common.md")]
pub trait EventGroupMethods: EventGroupHandle {
    /// Set the specified bits.
    #[inline]
    fn set(&self, bits: EventGroupBits) -> Result<(), UpdateEventGroupError> {
        // Safety: `EventGroup` represents a permission to access the
        //         referenced object.
        unsafe { <Self::System as raw::KernelEventGroup>::raw_event_group_set(self.id(), bits) }
    }

    /// Clear the specified bits.
    #[inline]
    fn clear(&self, bits: EventGroupBits) -> Result<(), UpdateEventGroupError> {
        // Safety: `EventGroup` represents a permission to access the
        //         referenced object.
        unsafe { <Self::System as raw::KernelEventGroup>::raw_event_group_clear(self.id(), bits) }
    }

    /// Get the currently set bits.
    #[inline]
    fn get(&self) -> Result<EventGroupBits, GetEventGroupError> {
        // Safety: `EventGroup` represents a permission to access the
        //         referenced object.
        unsafe { <Self::System as raw::KernelEventGroup>::raw_event_group_get(self.id()) }
    }

    /// Wait for all or any of the specified bits to be set. Optionally, clear
    /// the specified bits.
    ///
    /// Returns the currently set bits. If `EventGroupWaitFlags::CLEAR` is
    /// specified, this method returns the bits before clearing.
    ///
    /// This system service may block. Therefore, calling this method is not
    /// allowed in [a non-waitable context] and will return `Err(BadContext)`.
    ///
    /// [a non-waitable context]: crate#contexts
    #[inline]
    fn wait(
        &self,
        bits: EventGroupBits,
        flags: EventGroupWaitFlags,
    ) -> Result<EventGroupBits, WaitEventGroupError> {
        // Safety: `EventGroup` represents a permission to access the
        //         referenced object.
        unsafe {
            <Self::System as raw::KernelEventGroup>::raw_event_group_wait(self.id(), bits, flags)
        }
    }

    /// [`wait`](Self::wait) with timeout.
    #[inline]
    fn wait_timeout(
        &self,
        bits: EventGroupBits,
        flags: EventGroupWaitFlags,
        timeout: Duration,
    ) -> Result<EventGroupBits, WaitEventGroupTimeoutError> {
        // Safety: `EventGroup` represents a permission to access the
        //         referenced object.
        unsafe {
            <Self::System as raw::KernelEventGroup>::raw_event_group_wait_timeout(
                self.id(),
                bits,
                flags,
                timeout,
            )
        }
    }

    /// Non-blocking version of [`wait`](Self::wait). Returns immediately with
    /// [`PollEventGroupError::Timeout`] if the unblocking condition is not
    #[inline]
    /// satisfied.
    fn poll(
        &self,
        bits: EventGroupBits,
        flags: EventGroupWaitFlags,
    ) -> Result<EventGroupBits, PollEventGroupError> {
        // Safety: `EventGroup` represents a permission to access the
        //         referenced object.
        unsafe {
            <Self::System as raw::KernelEventGroup>::raw_event_group_poll(self.id(), bits, flags)
        }
    }
}

impl<T: EventGroupHandle> EventGroupMethods for T {}

// ----------------------------------------------------------------------------

/// The definer (static builder) for [`EventGroupRef`].
#[must_use = "must call `finish()` to complete definition"]
pub struct EventGroupDefiner<System: raw::KernelEventGroup> {
    inner: raw_cfg::EventGroupDescriptor<System>,
}

impl<System: raw::KernelEventGroup> EventGroupDefiner<System> {
    const fn new() -> Self {
        Self {
            inner: raw_cfg::EventGroupDescriptor {
                phantom: core::marker::PhantomData,
                initial_bits: 0,
                queue_order: raw::QueueOrder::TaskPriority,
            },
        }
    }

    /// Specify the initial bit pattern.
    pub const fn initial(self, initial: EventGroupBits) -> Self {
        Self {
            inner: raw_cfg::EventGroupDescriptor {
                initial_bits: initial,
                ..self.inner
            },
        }
    }

    /// Specify how tasks are sorted in the wait queue of the event group.
    /// Defaults to [`QueueOrder::TaskPriority`] when unspecified.
    ///
    /// [`QueueOrder::TaskPriority`]: raw::QueueOrder::TaskPriority
    pub const fn queue_order(self, queue_order: raw::QueueOrder) -> Self {
        Self {
            inner: raw_cfg::EventGroupDescriptor {
                queue_order,
                ..self.inner
            },
        }
    }

    /// Complete the definition of an event group, returning a reference to the
    /// event group.
    pub const fn finish<C: ~const raw_cfg::CfgEventGroup<System = System>>(
        self,
        c: &mut Cfg<C>,
    ) -> StaticEventGroup<System> {
        let id = c.raw().event_group_define(self.inner, ());
        unsafe { EventGroupRef::from_id(id) }
    }
}