Skip to main content

Gate

Struct Gate 

Source
pub struct Gate { /* private fields */ }
Expand description

Gate is a synchronization primitive that blocks tasks from entering a critical section until they are allowed to do so.

Implementations§

Source§

impl Gate

Source

pub const fn new() -> Self

Creates a new Gate.

§Examples
use saa::Gate;

let gate = Gate::new();
Source

pub fn state(&self, mo: Ordering) -> State

Returns the current state of the Gate.

§Examples
use std::sync::atomic::Ordering::Relaxed;

use saa::Gate;
use saa::gate::State;

let gate = Gate::default();

assert_eq!(gate.state(Relaxed), State::Controlled);
Source

pub fn reset(&self) -> Option<State>

Resets the Gate to its initial state if it is not in a Controlled state.

Returns the previous state of the Gate.

§Examples
use saa::Gate;
use saa::gate::State;

let gate = Gate::default();

assert_eq!(gate.reset(), None);

gate.seal();

assert_eq!(gate.reset(), Some(State::Sealed));
Source

pub fn permit(&self) -> Result<usize, State>

Permits waiting tasks to enter the Gate if the Gate is in a Controlled state.

Returns the number of permitted tasks.

§Errors

Returns an Error if the Gate is not in a Controlled state.

§Examples
use std::sync::Arc;
use std::thread;

use saa::Gate;
use saa::gate::State;

let gate = Arc::new(Gate::default());

let gate_clone = gate.clone();

let thread = thread::spawn(move || {
    assert_eq!(gate_clone.enter_sync(), Ok(State::Controlled));
});

loop {
    if gate.permit() == Ok(1) {
        break;
    }
}

thread.join().unwrap();
Source

pub fn reject(&self) -> Result<usize, State>

Rejects waiting tasks from entering the Gate if the Gate is in a Controlled state.

Returns the number of rejected tasks.

§Errors

Returns an Error if the Gate is not in a Controlled state.

§Examples
use std::sync::Arc;
use std::thread;

use saa::Gate;
use saa::gate::Error;

let gate = Arc::new(Gate::default());

let gate_clone = gate.clone();

let thread = thread::spawn(move || {
    assert_eq!(gate_clone.enter_sync(), Err(Error::Rejected));
});

loop {
    if gate.reject() == Ok(1) {
        break;
    }
}

thread.join().unwrap();
Source

pub fn open(&self) -> (State, usize)

Opens the Gate to allow any tasks to enter it.

Returns the number of tasks that were waiting to enter it.

§Examples
use std::sync::atomic::Ordering::Relaxed;

use saa::Gate;
use saa::gate::State;

let gate = Gate::default();
assert_eq!(gate.state(Relaxed), State::Controlled);

let (prev_state, count) = gate.open();

assert_eq!(prev_state, State::Controlled);
assert_eq!(count, 0);
assert_eq!(gate.state(Relaxed), State::Open);
Source

pub fn seal(&self) -> (State, usize)

Seals the Gate to disallow tasks from entering.

Returns the previous state of the Gate and the number of tasks that were waiting to enter the Gate.

§Examples
use std::sync::atomic::Ordering::Relaxed;

use saa::Gate;
use saa::gate::State;

let gate = Gate::default();

let (prev_state, count) = gate.seal();

assert_eq!(prev_state, State::Controlled);
assert_eq!(count, 0);
assert_eq!(gate.state(Relaxed), State::Sealed);
Source

pub async fn enter_async(&self) -> Result<State, Error>

Enters the Gate asynchronously.

This method does not return until Gate::open, Gate::permit, Gate::reject, or Gate::seal is invoked afterwards by other tasks, or the current task is cancelled.

Returns the current state of the Gate.

§Errors

Returns an Error if it failed to enter the Gate.

§Examples
use futures::future;
use saa::Gate;

let gate = Gate::default();

let a = async {
    assert!(gate.enter_async().await.is_ok());
};
let b = async {
    gate.permit();
};
future::join(a, b);
Source

pub fn enter_sync(&self) -> Result<State, Error>

Enters the Gate synchronously.

This method does not return until Gate::open, Gate::permit, Gate::reject, or Gate::seal is invoked afterwards by other tasks.

Returns the current state of the Gate.

§Errors

Returns an Error if it failed to enter the Gate.

§Examples
use std::sync::Arc;
use std::thread;

use saa::Gate;
use saa::gate::State;

let gate = Arc::new(Gate::default());

let gate_clone = gate.clone();
let thread_1 = thread::spawn(move || {
    assert_eq!(gate_clone.enter_sync(), Ok(State::Controlled));
});

let gate_clone = gate.clone();
let thread_2 = thread::spawn(move || {
    assert_eq!(gate_clone.enter_sync(), Ok(State::Controlled));
});

let mut count = 0;
while count != 2 {
    if let Ok(n) = gate.permit() {
        count += n;
    }
}

thread_1.join().unwrap();
thread_2.join().unwrap();
Source

pub async fn enter_async_with<F: FnOnce()>( &self, begin_wait: F, ) -> Result<State, Error>

Enters the Gate asynchronously with a wait callback.

Returns the current state of the Gate. The callback is invoked when the task starts waiting.

§Errors

Returns an Error if it failed to enter the Gate.

§Examples
use futures::future;
use saa::Gate;

let gate = Gate::default();

let a = async {
    let mut wait = false;
    assert!(gate.enter_async_with(|| wait = true).await.is_ok());
};
let b = async {
   gate.permit();
};
future::join(a, b);
Source

pub fn enter_sync_with<F: FnOnce()>( &self, begin_wait: F, ) -> Result<State, Error>

Enters the Gate synchronously with a wait callback.

Returns the current state of the Gate. The callback is invoked when the task starts waiting.

§Errors

Returns an Error if it failed to enter the Gate.

§Examples
use std::sync::Arc;
use std::thread;

use saa::Gate;
use saa::gate::State;

let gate = Arc::new(Gate::default());

let gate_clone = gate.clone();
let thread_1 = thread::spawn(move || {
    let mut wait = false;
    assert_eq!(gate_clone.enter_sync_with(|| wait = true), Ok(State::Controlled));
});

let gate_clone = gate.clone();
let thread_2 = thread::spawn(move || {
    let mut wait = false;
    assert_eq!(gate_clone.enter_sync_with(|| wait = true), Ok(State::Controlled));
});

let mut count = 0;
while count != 2 {
    if let Ok(n) = gate.permit() {
        count += n;
    }
}

thread_1.join().unwrap();
thread_2.join().unwrap();
Source

pub fn register_pager<'g>( &'g self, pager: &mut Pin<&mut Pager<'g, Self>>, is_sync: bool, ) -> bool

Registers a Pager to allow it to get a permit to enter the Gate remotely.

is_sync indicates whether the Pager will be polled asynchronously (false) or synchronously (true).

Returns false if the Pager was already registered.

§Examples
use std::pin::pin;
use std::sync::Arc;
use std::thread;

use saa::{Gate, Pager};
use saa::gate::State;

let gate = Arc::new(Gate::default());

let mut pinned_pager = pin!(Pager::default());

assert!(gate.register_pager(&mut pinned_pager, true));
assert!(!gate.register_pager(&mut pinned_pager, true));

let gate_clone = gate.clone();
let thread = thread::spawn(move || {
    assert_eq!(gate_clone.permit(), Ok(1));
});

thread.join().unwrap();

assert_eq!(pinned_pager.poll_sync(), Ok(State::Controlled));

Trait Implementations§

Source§

impl Debug for Gate

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Gate

Source§

fn default() -> Gate

Returns the “default value” for a type. Read more
Source§

impl Drop for Gate

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl SyncResult for Gate

Source§

type Result = Result<State, Error>

Operation result type.
Source§

fn to_result(value: u8, pager_error: Option<Error>) -> Self::Result

Converts a u8 value into a Self::Result.

Auto Trait Implementations§

§

impl !Freeze for Gate

§

impl RefUnwindSafe for Gate

§

impl Send for Gate

§

impl Sync for Gate

§

impl Unpin for Gate

§

impl UnsafeUnpin for Gate

§

impl UnwindSafe for Gate

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.