vex_rt/rtos/
semaphore.rs

1use core::{convert::TryInto, time::Duration};
2
3use crate::{
4    bindings,
5    error::{from_errno, Error, SentinelError},
6};
7
8/// Represents a FreeRTOS counting semaphore.
9pub struct Semaphore(bindings::sem_t);
10
11impl Semaphore {
12    #[inline]
13    /// Creates a new semaphore. Panics on failure; see [`Semaphore::try_new`].
14    pub fn new(max_count: u32, init_count: u32) -> Self {
15        Self::try_new(max_count, init_count)
16            .unwrap_or_else(|err| panic!("failed to create semaphore: {}", err))
17    }
18
19    /// Creates a new semaphore.
20    pub fn try_new(max_count: u32, init_count: u32) -> Result<Self, Error> {
21        Ok(Self(
22            unsafe { bindings::sem_create(max_count, init_count) }.check()?,
23        ))
24    }
25
26    #[inline]
27    /// Blocks up to `timeout` until an instance of the semaphore can be taken
28    /// (i.e., its count decremented). If the semaphore cannot be taken (due
29    /// to timeout or other reason), an error is returned.
30    pub fn wait(&self, timeout: Duration) -> Result<(), Error> {
31        if unsafe { bindings::sem_wait(self.0, timeout.as_millis().try_into()?) } {
32            Ok(())
33        } else {
34            Err(from_errno())
35        }
36    }
37
38    #[inline]
39    /// Increments the semaphore's count. If the semaphore cannot be given, an
40    /// error is returned.
41    pub fn post(&self) -> Result<(), Error> {
42        if unsafe { bindings::sem_post(self.0) } {
43            Ok(())
44        } else {
45            Err(from_errno())
46        }
47    }
48
49    #[inline]
50    /// Gets the semaphore's current count.
51    pub fn count(&self) -> u32 {
52        unsafe { bindings::sem_get_count(self.0) }
53    }
54}
55
56impl Drop for Semaphore {
57    fn drop(&mut self) {
58        unsafe { bindings::sem_delete(self.0) }
59    }
60}
61
62unsafe impl Send for Semaphore {}
63
64unsafe impl Sync for Semaphore {}