Skip to main content

ArcStdMonitor

Struct ArcStdMonitor 

Source
pub struct ArcStdMonitor<T> { /* private fields */ }
Expand description

Arc-wrapped monitor for shared condition-based state coordination.

ArcStdMonitor stores a StdMonitor behind an Arc, so callers can clone the monitor handle directly without writing Arc::new(StdMonitor::new(...)). It preserves the same guard-based waiting, predicate-based waiting, and poison recovery semantics as StdMonitor. It implements Deref and AsRef so callers can pass it to APIs that expect a StdMonitor reference.

§Type Parameters

  • T - The state protected by this monitor.

§Example

use std::thread;

use qubit_lock::lock::ArcStdMonitor;

let monitor = ArcStdMonitor::new(false);
let waiter_monitor = monitor.clone();

let waiter = thread::spawn(move || {
    waiter_monitor.wait_until(
        |ready| *ready,
        |ready| {
            *ready = false;
        },
    );
});

monitor.write(|ready| {
    *ready = true;
});
monitor.notify_all();

waiter.join().expect("waiter should finish");
assert!(!monitor.read(|ready| *ready));

Implementations§

Source§

impl<T> ArcStdMonitor<T>

Source

pub fn new(state: T) -> Self

Creates an Arc-wrapped monitor protecting the supplied state value.

§Arguments
  • state - Initial state protected by the monitor.
§Returns

A cloneable monitor handle initialized with the supplied state.

Source

pub fn lock(&self) -> StdMonitorGuard<'_, T>

Acquires the shared monitor and returns a guard.

This delegates to StdMonitor::lock. The returned StdMonitorGuard keeps the monitor mutex locked until it is dropped. It can also wait on the monitor’s condition variable through StdMonitorGuard::wait or StdMonitorGuard::wait_timeout.

If the underlying mutex is poisoned, this method recovers the inner state and still returns a guard.

§Returns

A guard that provides read and write access to the protected state.

§Example
use qubit_lock::lock::ArcStdMonitor;

let monitor = ArcStdMonitor::new(1);
{
    let mut value = monitor.lock();
    *value += 1;
}

assert_eq!(monitor.read(|value| *value), 2);
Source

pub fn read<R, F>(&self, f: F) -> R
where F: FnOnce(&T) -> R,

Acquires the monitor and reads the protected state.

This delegates to StdMonitor::read. The closure runs while the monitor mutex is held, so keep it short and avoid long blocking work.

§Arguments
  • f - Closure that receives an immutable reference to the state.
§Returns

The value returned by f.

Source

pub fn write<R, F>(&self, f: F) -> R
where F: FnOnce(&mut T) -> R,

Acquires the monitor and mutates the protected state.

This delegates to StdMonitor::write. Callers should explicitly invoke Self::notify_one or Self::notify_all after changing state that a waiting thread may observe.

§Arguments
  • f - Closure that receives a mutable reference to the state.
§Returns

The value returned by f.

Source

pub fn wait_notify(&self, timeout: Duration) -> WaitTimeoutStatus

Waits for a notification or timeout without checking state.

This delegates to StdMonitor::wait_notify. Most coordination code should prefer Self::wait_while, Self::wait_until, or an explicit StdMonitorGuard loop.

Condition variables may wake spuriously, so WaitTimeoutStatus::Woken does not prove that a notifier changed the state.

§Arguments
  • timeout - Maximum duration to wait for a notification.
§Returns

WaitTimeoutStatus::Woken if the wait returned before the timeout, or WaitTimeoutStatus::TimedOut if the timeout elapsed.

§Example
use std::time::Duration;

use qubit_lock::lock::{ArcStdMonitor, WaitTimeoutStatus};

let monitor = ArcStdMonitor::new(false);
let status = monitor.wait_notify(Duration::from_millis(1));

assert_eq!(status, WaitTimeoutStatus::TimedOut);
Source

pub fn wait_while<R, P, F>(&self, waiting: P, f: F) -> R
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits while a predicate remains true, then mutates the protected state.

This delegates to StdMonitor::wait_while. The predicate is evaluated while holding the monitor mutex, and the closure runs while the mutex is still held after the predicate stops blocking.

This method may block indefinitely if no thread changes the state so that waiting becomes false and sends a notification.

§Arguments
  • waiting - Predicate that returns true while the caller should keep waiting.
  • f - Closure that receives mutable access after waiting is no longer required.
§Returns

The value returned by f.

§Example
use std::thread;

use qubit_lock::lock::ArcStdMonitor;

let monitor = ArcStdMonitor::new(Vec::<i32>::new());
let worker_monitor = monitor.clone();

let worker = thread::spawn(move || {
    worker_monitor.wait_while(
        |items| items.is_empty(),
        |items| items.pop().expect("item should be ready"),
    )
});

monitor.write(|items| items.push(7));
monitor.notify_one();

assert_eq!(worker.join().expect("worker should finish"), 7);
Source

pub fn wait_until<R, P, F>(&self, ready: P, f: F) -> R
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits until the protected state satisfies a predicate, then mutates it.

This delegates to StdMonitor::wait_until. It may block indefinitely if no thread changes the state to satisfy the predicate and sends a notification.

§Arguments
  • ready - Predicate that returns true when the state is ready.
  • f - Closure that receives mutable access to the ready state.
§Returns

The value returned by f.

Source

pub fn wait_timeout_while<R, P, F>( &self, timeout: Duration, waiting: P, f: F, ) -> WaitTimeoutResult<R>
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits while a predicate remains true, with an overall time limit.

This delegates to StdMonitor::wait_timeout_while. If waiting becomes false before timeout expires, f runs while the monitor lock is still held. If the timeout expires first, the closure is not called.

§Arguments
  • timeout - Maximum total duration to wait.
  • waiting - Predicate that returns true while the caller should continue waiting.
  • f - Closure that receives mutable access when waiting is no longer required.
§Returns

WaitTimeoutResult::Ready with the value returned by f when the predicate stops blocking before the timeout. Returns WaitTimeoutResult::TimedOut when the timeout expires first.

§Example
use std::time::Duration;

use qubit_lock::lock::{ArcStdMonitor, WaitTimeoutResult};

let monitor = ArcStdMonitor::new(Vec::<i32>::new());
let result = monitor.wait_timeout_while(
    Duration::from_millis(1),
    |items| items.is_empty(),
    |items| items.pop(),
);

assert_eq!(result, WaitTimeoutResult::TimedOut);
Source

pub fn wait_timeout_until<R, P, F>( &self, timeout: Duration, ready: P, f: F, ) -> WaitTimeoutResult<R>
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits until a predicate becomes true, with an overall time limit.

This delegates to StdMonitor::wait_timeout_until. If ready becomes true before timeout expires, f runs while the monitor lock is still held. If the timeout expires first, the closure is not called.

§Arguments
  • timeout - Maximum total duration to wait.
  • ready - Predicate that returns true when the caller may continue.
  • f - Closure that receives mutable access to the ready state.
§Returns

WaitTimeoutResult::Ready with the value returned by f when the predicate becomes true before the timeout. Returns WaitTimeoutResult::TimedOut when the timeout expires first.

§Example
use std::{
    thread,
    time::Duration,
};

use qubit_lock::lock::{ArcStdMonitor, WaitTimeoutResult};

let monitor = ArcStdMonitor::new(false);
let worker_monitor = monitor.clone();

let worker = thread::spawn(move || {
    worker_monitor.wait_timeout_until(
        Duration::from_secs(1),
        |ready| *ready,
        |ready| {
            *ready = false;
            5
        },
    )
});

monitor.write(|ready| *ready = true);
monitor.notify_one();

assert_eq!(
    worker.join().expect("worker should finish"),
    WaitTimeoutResult::Ready(5),
);
Source

pub fn notify_one(&self)

Wakes one thread waiting on this monitor’s condition variable.

Notifications do not carry state by themselves. A waiting thread only proceeds safely after rechecking the protected state. Call this after changing state that may make one waiter able to continue.

Source

pub fn notify_all(&self)

Wakes all threads waiting on this monitor’s condition variable.

Notifications do not carry state by themselves. Every awakened thread must recheck the protected state before continuing. Call this after a state change that may allow multiple waiters to make progress.

Methods from Deref<Target = StdMonitor<T>>§

Source

pub fn lock(&self) -> StdMonitorGuard<'_, T>

Acquires the monitor and returns a guard for explicit state-machine code.

The returned StdMonitorGuard keeps the monitor mutex locked until the guard is dropped. It can also be passed through StdMonitorGuard::wait or StdMonitorGuard::wait_timeout to temporarily release the lock while waiting on this monitor’s condition variable.

If the mutex is poisoned, this method recovers the inner state and still returns a guard.

§Returns

A guard that provides read and write access to the protected state.

§Example
use qubit_lock::lock::StdMonitor;

let monitor = StdMonitor::new(1);
{
    let mut value = monitor.lock();
    *value += 1;
}

assert_eq!(monitor.read(|value| *value), 2);
Source

pub fn read<R, F>(&self, f: F) -> R
where F: FnOnce(&T) -> R,

Acquires the monitor and reads the protected state.

The closure runs while the mutex is held. Keep the closure short and do not call code that may block for a long time.

If the mutex is poisoned, this method recovers the inner state and still executes the closure.

§Arguments
  • f - Closure that receives an immutable reference to the state.
§Returns

The value returned by the closure.

§Example
use qubit_lock::lock::StdMonitor;

let monitor = StdMonitor::new(10_i32);
let n = monitor.read(|x| *x);
assert_eq!(n, 10);
Source

pub fn write<R, F>(&self, f: F) -> R
where F: FnOnce(&mut T) -> R,

Acquires the monitor and mutates the protected state.

The closure runs while the mutex is held. This method only changes the state; callers should explicitly call Self::notify_one or Self::notify_all after changing a condition that waiters may be observing.

If the mutex is poisoned, this method recovers the inner state and still executes the closure.

§Arguments
  • f - Closure that receives a mutable reference to the state.
§Returns

The value returned by the closure.

§Example
use qubit_lock::lock::StdMonitor;

let monitor = StdMonitor::new(String::new());
let len = monitor.write(|s| {
    s.push_str("hi");
    s.len()
});
assert_eq!(len, 2);
Source

pub fn wait_notify(&self, timeout: Duration) -> WaitTimeoutStatus

Waits for a notification or timeout without checking state.

This convenience method locks the monitor, waits once on the condition variable, and returns why the timed wait completed. It is useful only when the caller genuinely needs a notification wait without inspecting state before or after the wait. Most coordination code should prefer Self::wait_while, Self::wait_until, or the explicit StdMonitorGuard::wait_timeout loop.

Condition variables may wake spuriously, so WaitTimeoutStatus::Woken does not prove that a notifier changed the state.

If the mutex is poisoned, this method recovers the inner state and continues waiting.

§Arguments
  • timeout - Maximum duration to wait for a notification.
§Returns

WaitTimeoutStatus::Woken if the wait returned before the timeout, or WaitTimeoutStatus::TimedOut if the timeout elapsed.

§Example
use std::time::Duration;

use qubit_lock::lock::{StdMonitor, WaitTimeoutStatus};

let monitor = StdMonitor::new(false);
let status = monitor.wait_notify(Duration::from_millis(1));

assert_eq!(status, WaitTimeoutStatus::TimedOut);
Source

pub fn wait_while<R, P, F>(&self, waiting: P, f: F) -> R
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits while a predicate remains true, then mutates the protected state.

This is the monitor equivalent of the common while condition { wait } guarded-suspension pattern. The predicate is evaluated while holding the mutex. If it returns true, the current thread waits on the condition variable and atomically releases the mutex. After a notification or spurious wakeup, the mutex is reacquired and the predicate is evaluated again. When the predicate returns false, f runs while the mutex is still held.

This method may block indefinitely if no thread changes the state so that waiting becomes false and sends a notification.

If the mutex is poisoned before or during the wait, this method recovers the inner state and continues waiting or executes the closure.

§Arguments
  • waiting - Predicate that returns true while the caller should keep waiting.
  • f - Closure that receives mutable access after waiting is no longer required.
§Returns

The value returned by f.

§Example
use std::{
    sync::Arc,
    thread,
};

use qubit_lock::lock::StdMonitor;

let monitor = Arc::new(StdMonitor::new(Vec::<i32>::new()));
let worker_monitor = Arc::clone(&monitor);

let worker = thread::spawn(move || {
    worker_monitor.wait_while(
        |items| items.is_empty(),
        |items| items.pop().expect("item should be ready"),
    )
});

monitor.write(|items| items.push(7));
monitor.notify_one();

assert_eq!(worker.join().expect("worker should finish"), 7);
Source

pub fn wait_until<R, P, F>(&self, ready: P, f: F) -> R
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits until the protected state satisfies a predicate, then mutates it.

This is the positive-predicate counterpart of Self::wait_while. The predicate is evaluated while holding the mutex. If it returns false, the current thread waits on the condition variable and atomically releases the mutex. After a notification or spurious wakeup, the mutex is reacquired and the predicate is evaluated again. When the predicate returns true, f runs while the mutex is still held.

This method may block indefinitely if no thread changes the state to satisfy the predicate and sends a notification.

If the mutex is poisoned before or during the wait, this method recovers the inner state and continues waiting or executes the closure.

§Arguments
  • ready - Predicate that returns true when the state is ready.
  • f - Closure that receives mutable access to the ready state.
§Returns

The value returned by f after the predicate has become true.

§Example
use std::{
    sync::Arc,
    thread,
};

use qubit_lock::lock::StdMonitor;

let monitor = Arc::new(StdMonitor::new(false));
let waiter_monitor = Arc::clone(&monitor);

let waiter = thread::spawn(move || {
    waiter_monitor.wait_until(
        |ready| *ready,
        |ready| {
            *ready = false;
            "done"
        },
    )
});

monitor.write(|ready| *ready = true);
monitor.notify_one();

assert_eq!(waiter.join().expect("waiter should finish"), "done");
Source

pub fn wait_timeout_while<R, P, F>( &self, timeout: Duration, waiting: P, f: F, ) -> WaitTimeoutResult<R>
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits while a predicate remains true, with an overall time limit.

This method is the timeout-aware form of Self::wait_while. It keeps rechecking waiting under the monitor lock and waits only for the remaining portion of timeout. If waiting becomes false before the timeout expires, f runs while the lock is still held. If the timeout expires first, the closure is not called.

Condition variables may wake spuriously, and timeout status alone is not used as proof that the predicate is still true; the predicate is always rechecked under the lock.

If the mutex is poisoned before or during the wait, this method recovers the inner state and continues waiting or executes the closure.

§Arguments
  • timeout - Maximum total duration to wait.
  • waiting - Predicate that returns true while the caller should continue waiting.
  • f - Closure that receives mutable access when waiting is no longer required.
§Returns

WaitTimeoutResult::Ready with the value returned by f when the predicate stops blocking before the timeout. Returns WaitTimeoutResult::TimedOut when the timeout expires first.

§Example
use std::time::Duration;

use qubit_lock::lock::{StdMonitor, WaitTimeoutResult};

let monitor = StdMonitor::new(Vec::<i32>::new());
let result = monitor.wait_timeout_while(
    Duration::from_millis(1),
    |items| items.is_empty(),
    |items| items.pop(),
);

assert_eq!(result, WaitTimeoutResult::TimedOut);
Source

pub fn wait_timeout_until<R, P, F>( &self, timeout: Duration, ready: P, f: F, ) -> WaitTimeoutResult<R>
where P: FnMut(&T) -> bool, F: FnOnce(&mut T) -> R,

Waits until a predicate becomes true, with an overall time limit.

This is the positive-predicate counterpart of Self::wait_timeout_while. If ready becomes true before the timeout expires, f runs while the monitor lock is still held. If the timeout expires first, the closure is not called.

Condition variables may wake spuriously, and timeout status alone is not used as proof that the predicate is still false; the predicate is always rechecked under the lock.

If the mutex is poisoned before or during the wait, this method recovers the inner state and continues waiting or executes the closure.

§Arguments
  • timeout - Maximum total duration to wait.
  • ready - Predicate that returns true when the caller may continue.
  • f - Closure that receives mutable access to the ready state.
§Returns

WaitTimeoutResult::Ready with the value returned by f when the predicate becomes true before the timeout. Returns WaitTimeoutResult::TimedOut when the timeout expires first.

§Example
use std::{
    sync::Arc,
    thread,
    time::Duration,
};

use qubit_lock::lock::{StdMonitor, WaitTimeoutResult};

let monitor = Arc::new(StdMonitor::new(false));
let waiter_monitor = Arc::clone(&monitor);

let waiter = thread::spawn(move || {
    waiter_monitor.wait_timeout_until(
        Duration::from_secs(1),
        |ready| *ready,
        |ready| {
            *ready = false;
            5
        },
    )
});

monitor.write(|ready| *ready = true);
monitor.notify_one();

assert_eq!(
    waiter.join().expect("waiter should finish"),
    WaitTimeoutResult::Ready(5),
);
Source

pub fn notify_one(&self)

Wakes one thread waiting on this monitor’s condition variable.

Notifications do not carry state by themselves. A waiting thread only proceeds safely after rechecking the protected state. Call this after changing state that may make one waiter able to continue.

§Example
use std::thread;

use qubit_lock::lock::ArcStdMonitor;

let monitor = ArcStdMonitor::new(0_u32);
let waiter = {
    let m = monitor.clone();
    thread::spawn(move || {
        m.wait_until(|n| *n > 0, |n| {
            *n -= 1;
        });
    })
};

monitor.write(|n| *n = 1);
monitor.notify_one();
waiter.join().expect("waiter should finish");
Source

pub fn notify_all(&self)

Wakes all threads waiting on this monitor’s condition variable.

Notifications do not carry state by themselves. Every awakened thread must recheck the protected state before continuing. Call this after a state change that may allow multiple waiters to make progress.

§Example
use std::thread;

use qubit_lock::lock::ArcStdMonitor;

let monitor = ArcStdMonitor::new(false);
let mut handles = Vec::new();
for _ in 0..2 {
    let m = monitor.clone();
    handles.push(thread::spawn(move || {
        m.wait_until(|ready| *ready, |_| ());
    }));
}

monitor.write(|ready| *ready = true);
monitor.notify_all();
for h in handles {
    h.join().expect("waiter should finish");
}

Trait Implementations§

Source§

impl<T> AsRef<StdMonitor<T>> for ArcStdMonitor<T>

Source§

fn as_ref(&self) -> &StdMonitor<T>

Returns a reference to the underlying standard monitor.

This is useful when callers need an explicit StdMonitor reference while keeping the cloneable ArcStdMonitor handle.

Source§

impl<T> Clone for ArcStdMonitor<T>

Source§

fn clone(&self) -> Self

Clones this monitor handle.

The cloned handle shares the same protected state and condition variable with the original.

§Returns

A new handle sharing the same monitor state.

1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Default> Default for ArcStdMonitor<T>

Source§

fn default() -> Self

Creates an Arc-wrapped monitor containing T::default().

§Returns

A cloneable monitor handle protecting the default value for T.

Source§

impl<T> Deref for ArcStdMonitor<T>

Source§

fn deref(&self) -> &Self::Target

Dereferences this wrapper to the underlying standard monitor.

Method-call dereferencing lets callers use native StdMonitor APIs directly, while this wrapper still provides cloneable ownership.

Source§

type Target = StdMonitor<T>

The resulting type after dereferencing.

Auto Trait Implementations§

§

impl<T> Freeze for ArcStdMonitor<T>

§

impl<T> RefUnwindSafe for ArcStdMonitor<T>

§

impl<T> Send for ArcStdMonitor<T>
where T: Send,

§

impl<T> Sync for ArcStdMonitor<T>
where T: Send,

§

impl<T> Unpin for ArcStdMonitor<T>

§

impl<T> UnsafeUnpin for ArcStdMonitor<T>

§

impl<T> UnwindSafe for ArcStdMonitor<T>

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.