flag_bearer_core/lib.rs
1#![no_std]
2#![deny(unsafe_code)]
3
4/// The trait defining how semaphores behave.
5///
6/// The usage of this state is as follows:
7/// ```
8/// # use flag_bearer_core::SemaphoreState;
9/// # use std::sync::Mutex;
10/// fn get_permit<S: SemaphoreState>(s: &Mutex<S>, mut params: S::Params) -> S::Permit {
11/// loop {
12/// let mut s = s.lock().unwrap();
13/// match s.acquire(params) {
14/// Ok(permit) => break permit,
15/// Err(p) => params = p,
16/// }
17///
18/// // sleep/spin/yield until time to try again
19/// }
20/// }
21///
22/// fn return_permit<S: SemaphoreState>(s: &Mutex<S>, permit: S::Permit) {
23/// s.lock().unwrap().release(permit);
24/// }
25/// ```
26pub trait SemaphoreState {
27 /// What type is used to request permits.
28 ///
29 /// An example of this could be `usize` for a counting semaphore,
30 /// if you want to support `acquire_many` type requests.
31 type Params;
32
33 /// The type representing the current permit allocation.
34 ///
35 /// If you have a counting semaphore, this could be the number
36 /// of permits acquired. If this is more like a connection pool,
37 /// this could be a specific object allocation.
38 type Permit;
39
40 /// Acquire a permit given the params.
41 ///
42 /// If a permit could not be acquired with the params, return an error with the
43 /// original params back.
44 ///
45 /// # Panics
46 ///
47 /// This method should not panic. If it does, the params are lost and `self` may be
48 /// left half-updated, so the semaphore is *poisoned*: it stops handing out permits.
49 /// A blocking `acquire` then panics, while `try_acquire` reports the poison via its
50 /// error type.
51 fn acquire(&mut self, params: Self::Params) -> Result<Self::Permit, Self::Params>;
52
53 /// Return the permit back to the semaphore.
54 ///
55 /// Note: This is not guaranteed to be called for every acquire call.
56 /// Permits can be modified or forgotten, or created at will.
57 fn release(&mut self, permit: Self::Permit);
58}