Структура Condvar

#![allow(unused)]
fn main() {
pub struct Condvar { /* приватные поля */ }
}

Условная переменная.

Условные переменные представляют собой возможность блокировать поток до тех пор, пока не будет выполнено определенное условие.

Условные переменные обычно используются в паре с мьютексом. Как правило, условная переменная используется для защиты данных, а мьютекс используется для обеспечения эксклюзивного доступа к данным, в то время как условная переменная используется для сигнализации об изменении данных.

Этот модуль поддерживает два типа условных переменных:

  1. Condvar - стандартная реализация условной переменной, которая может быть создана с помощью Condvar::new().
  2. StaticCondvar - статическая инициализация условной переменной.

Пример

#![allow(unused)]
fn main() {
use std::sync::{Arc, Mutex, Condvar};
use std::thread;

let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);

// Внутренний поток, который будет устанавливать условие
thread::spawn(move|| {
    let (lock, cvar) = &*pair2;
    let mut started = lock.lock().unwrap();
    *started = true;
    // Уведомляем один ожидающий поток
    cvar.notify_one();
});

// Ждем, пока условие не станет true
let (lock, cvar) = &*pair;
let mut started = lock.lock().unwrap();
while !*started {
    started = cvar.wait(started).unwrap();
}
}

Методы

pub fn new() -> Condvar

Создает новую условную переменную.

Пример

#![allow(unused)]
fn main() {
use std::sync::Condvar;

let condvar = Condvar::new();
}

pub fn wait<'a, T>( &self, guard: MutexGuard<'a, T> ) -> LockResult<MutexGuard<'a, T>>

Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление.

Эта функция атомарно разблокирует указанный мьютекс и блокирует текущий поток. Когда поток блокируется, вызывающий поток должен обеспечить, чтобы охрана мьютекса была временно освобождена, чтобы позволить другим потокам получить доступ к данным, защищенным мьютексом.

Когда эта функция возвращается, указанная охрана мьютекса будет повторно получена.

Пример

#![allow(unused)]
fn main() {
use std::sync::{Arc, Mutex, Condvar};
use std::thread;

let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);

thread::spawn(move|| {
    let (lock, cvar) = &*pair2;
    let mut started = lock.lock().unwrap();
    *started = true;
    cvar.notify_one();
});

let (lock, cvar) = &*pair;
let mut started = lock.lock().unwrap();
while !*started {
    started = cvar.wait(started).unwrap();
}
}

pub fn wait_while<'a, T, F>( &self, guard: MutexGuard<'a, T>, condition: F ) -> LockResult<MutexGuard<'a, T>> where F: FnMut(&mut T) -> bool,

Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление и указанное условие не станет ложным.

Эта функция атомарно разблокирует указанный мьютекс и блокирует текущий поток. Когда поток блокируется, вызывающий поток должен обеспечить, чтобы охрана мьютекса была временно освобождена, чтобы позволить другим потокам получить доступ к данным, защищенным мьютексом.

Когда эта функция возвращается, указанная охрана мьютекса будет повторно получена.

Пример

#![allow(unused)]
fn main() {
use std::sync::{Arc, Mutex, Condvar};
use std::thread;

let pair = Arc::new((Mutex::new(true), Condvar::new()));
let pair2 = Arc::clone(&pair);

thread::spawn(move|| {
    let (lock, cvar) = &*pair2;
    let mut pending = lock.lock().unwrap();
    *pending = false;
    cvar.notify_one();
});

let (lock, cvar) = &*pair;
let mut pending = lock.lock().unwrap();
while *pending {
    pending = cvar.wait_while(pending, |pending| *pending).unwrap();
}
}

pub fn wait_timeout<'a, T>( &self, guard: MutexGuard<'a, T>, timeout: Duration ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>

Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление или не истечет указанное время ожидания.

Возвращаемое значение указывает, сколько времени осталось до истечения таймаута.

Пример

#![allow(unused)]
fn main() {
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
use std::time::Duration;

let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);

thread::spawn(move|| {
    let (lock, cvar) = &*pair2;
    let mut started = lock.lock().unwrap();
    *started = true;
    cvar.notify_one();
});

let (lock, cvar) = &*pair;
let mut started = lock.lock().unwrap();
loop {
    let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
    started = result.0;
    if *started {
        break;
    }
    if result.1.timed_out() {
        // Таймаут истек без получения уведомления
        break;
    }
}
}

pub fn wait_timeout_while<'a, T, F>( &self, guard: MutexGuard<'a, T>, timeout: Duration, condition: F ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> where F: FnMut(&mut T) -> bool,

Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление, указанное условие не станет ложным или не истечет указанное время ожидания.

Возвращаемое значение указывает, осталось ли время до истечения таймаута.

Пример

#![allow(unused)]
fn main() {
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
use std::time::Duration;

let pair = Arc::new((Mutex::new(true), Condvar::new()));
let pair2 = Arc::clone(&pair);

thread::spawn(move|| {
    let (lock, cvar) = &*pair2;
    let mut pending = lock.lock().unwrap();
    *pending = false;
    cvar.notify_one();
});

let (lock, cvar) = &*pair;
let mut pending = lock.lock().unwrap();
loop {
    let result = cvar.wait_timeout_while(
        pending, 
        Duration::from_millis(100), 
        |&mut pending| pending
    ).unwrap();
    pending = result.0;
    if !*pending {
        break;
    }
    if result.1.timed_out() {
        // Таймаут истек, но условие все еще истинно
        break;
    }
}
}

pub fn notify_one(&self)

Пробуждает один поток, ожидающий на этой условной переменной.

Если есть потоки, заблокированные на этой условной переменной, то этот вызов пробудит один из них.

Пример

#![allow(unused)]
fn main() {
use std::sync::{Arc, Mutex, Condvar};
use std::thread;

let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);

thread::spawn(move|| {
    let (lock, cvar) = &*pair2;
    let mut started = lock.lock().unwrap();
    *started = true;
    cvar.notify_one();
});

let (lock, cvar) = &*pair;
let mut started = lock.lock().unwrap();
while !*started {
    started = cvar.wait(started).unwrap();
}
}

pub fn notify_all(&self)

Пробуждает все потоки, ожидающие на этой условной переменной.

Этот метод гарантирует, что все потоки, заблокированные на этой условной переменной, будут пробуждены.

Пример

#![allow(unused)]
fn main() {
use std::sync::{Arc, Mutex, Condvar};
use std::thread;

let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);

for _ in 0..3 {
    let pair3 = Arc::clone(&pair2);
    thread::spawn(move|| {
        let (lock, cvar) = &*pair3;
        let mut started = lock.lock().unwrap();
        while !*started {
            started = cvar.wait(started).unwrap();
        }
    });
}

let (lock, cvar) = &*pair;
let mut started = lock.lock().unwrap();
*started = true;
cvar.notify_all();
}

Trait реализации

impl Debug for Condvar

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

Форматирует значение с использованием заданного форматировщика.

impl Default for Condvar

fn default() -> Condvar

Возвращает "значение по умолчанию" для типа.

Автоматические реализации Trait

impl RefUnwindSafe for Condvar

impl Send for Condvar

impl Sync for Condvar

impl UnwindSafe for Condvar

Blanket реализации

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

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

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

impl<T> From<T> for T

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

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

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

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