starina_api/signal.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
//! A semaphore-like API.
use core::fmt;
use starina_types::error::FtlError;
use starina_types::signal::SignalBits;
use crate::handle::OwnedHandle;
use crate::syscall;
/// A semaphore-like asynchronous inter-process communication primitive.
///
/// Each signal has 32-bit-wide bitfields. Updating the bitfields wakes up
/// waiting processes. You can update the bitfields multiple times before
/// it is cleared, but it can't tell how many times it was updated. In other
/// words, it guarantees bitfields are set at least once.
///
/// # [`Signal`] vs. [`Channel`](crate::channel::Channel)
///
/// While [`Signal`] cannot carry data more than bitfields,
/// it is more lightweight and faster than [`Channel`](crate::channel::Channel).
///
/// Use [`Signal`] when you need to notify other processes of an event, especially when you just want to wake up a sleeping process.
pub struct Signal {
handle: OwnedHandle,
}
impl Signal {
/// Creates a new signal.
pub fn create() -> Result<Signal, FtlError> {
let handle = syscall::signal_create()?;
Ok(Signal {
handle: OwnedHandle::from_raw(handle),
})
}
/// Instantiates the object from the given handle.
pub fn from_handle(handle: OwnedHandle) -> Signal {
Signal { handle }
}
/// Returns the handle.
pub fn handle(&self) -> &OwnedHandle {
&self.handle
}
/// Updates the signal. Non-blocking.
///
/// This bit-wise ORs the given value to the signal, and wakes up waiting
/// processes if any.
pub fn update(&self, value: SignalBits) -> Result<(), FtlError> {
syscall::signal_update(self.handle.id(), value)
}
/// Clears the signal, and returns the previous value. Non-blocking.
pub fn clear(&self) -> Result<SignalBits, FtlError> {
syscall::signal_clear(self.handle.id())
}
}
impl fmt::Debug for Signal {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
todo!()
}
}