pub struct Rendezvous { /* private fields */ }
Expand description
Rendezvous
is a synchronization primitive that allows two threads to rendezvous
at a certain point in the code before proceeding.
Implementations§
Source§impl Rendezvous
impl Rendezvous
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new instance of a Rendezvous
channel.
§Returns
The newly created rendezvous channel.
§Examples
use rendezvous::Rendezvous;
let rendezvous = Rendezvous::new();
Sourcepub fn fork_guard(&self) -> RendezvousGuard
pub fn fork_guard(&self) -> RendezvousGuard
Forks a guard off the Rendezvous
channel.
When all guards are dropped, Rendezvous::rendezvous
will proceed; until then, that
call blocks.
§Example
See Rendezvous::new
for a usage example.
Note that forking and not dropping a guard in the same thread is a deadlock:
use rendezvous::Rendezvous;
let mut rendezvous = Rendezvous::new();
let guard = rendezvous.fork_guard();
rendezvous.rendezvous(); // will deadlock
drop(guard);
Sourcepub fn rendezvous(self)
pub fn rendezvous(self)
Executes the rendezvous process.
§Example
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use rendezvous::{Rendezvous, RendezvousGuard};
// A slow worker function. Sleeps, then mutates a value.
fn slow_worker_fn(_guard: RendezvousGuard, mut value: Arc<Mutex<u32>>) {
thread::sleep(Duration::from_millis(400));
let mut value = value.lock().unwrap();
*value = 42;
}
// The guard that ensures synchronization across threads.
let rendezvous = Rendezvous::new();
// A value to mutate in a different thread.
let value = Arc::new(Mutex::new(0u32));
// Run the worker in a thread.
thread::spawn({
let guard = rendezvous.fork_guard();
let value = value.clone();
move || slow_worker_fn(guard, value)
});
// Block until the thread has finished its work.
rendezvous.rendezvous();
// The thread finished in time.
assert_eq!(*(value.lock().unwrap()), 42);
Note that forking and not dropping a guard in the same thread is a deadlock:
use rendezvous::Rendezvous;
let mut rendezvous = Rendezvous::new();
let guard = rendezvous.fork_guard();
rendezvous.rendezvous(); // will deadlock
drop(guard);
Sourcepub async fn rendezvous_async(self) -> Result<(), JoinError>
Available on crate feature tokio
only.
pub async fn rendezvous_async(self) -> Result<(), JoinError>
tokio
only.Asynchronously executes the rendezvous process.
§Usage notes
When the rendezvous channel is dropped without a call to Rendezvous::rendezvous_async
,
the currently executed will block until all rendezvous points are reached.
§Example
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use rendezvous::{Rendezvous, RendezvousGuard};
// A slow worker function. Sleeps, then mutates a value.
fn slow_worker_fn(_guard: RendezvousGuard, mut value: Arc<Mutex<u32>>) {
thread::sleep(Duration::from_millis(400));
let mut value = value.lock().unwrap();
*value = 42;
}
// The guard that ensures synchronization across threads.
let rendezvous = Rendezvous::new();
// A value to mutate in a different thread.
let value = Arc::new(Mutex::new(0u32));
// Run the worker in a thread.
thread::spawn({
let guard = rendezvous.fork_guard();
let value = value.clone();
move || slow_worker_fn(guard, value)
});
// Block until the thread has finished its work.
rendezvous.rendezvous_async().await.ok();
// The thread finished in time.
assert_eq!(*(value.lock().unwrap()), 42);
Sourcepub fn rendezvous_timeout(
&mut self,
timeout: Duration,
) -> Result<(), RendezvousTimeoutError>
pub fn rendezvous_timeout( &mut self, timeout: Duration, ) -> Result<(), RendezvousTimeoutError>
Executes the rendezvous process with a timeout.
§Example
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use rendezvous::{Rendezvous, RendezvousGuard, RendezvousTimeoutError};
// A slow worker function. Sleeps, then mutates a value.
fn slow_worker_fn(_guard: RendezvousGuard, mut value: Arc<Mutex<u32>>) {
thread::sleep(Duration::from_millis(400));
let mut value = value.lock().unwrap();
*value = 42;
}
// The guard that ensures synchronization across threads.
let mut rendezvous = Rendezvous::new();
// A value to mutate in a different thread.
let value = Arc::new(Mutex::new(0u32));
// Run the worker in a thread.
thread::spawn({
let guard = rendezvous.fork_guard();
let value = value.clone();
move || slow_worker_fn(guard, value)
});
// Wait briefly - this will fail.
let result = rendezvous.rendezvous_timeout(Duration::from_millis(10));
assert_eq!(result, Err(RendezvousTimeoutError::Timeout));
// Block until the thread has finished its work, or the timeout occurs.
let result = rendezvous.rendezvous_timeout(Duration::from_secs(1));
assert_eq!(result, Ok(()));
// The thread finished in time.
assert_eq!(*(value.lock().unwrap()), 42);
Note that forking and not dropping a guard is generally a deadlock, and a timeout will occur:
use std::time::Duration;
use rendezvous::{Rendezvous, RendezvousTimeoutError};
let mut rendezvous = Rendezvous::new();
let guard = rendezvous.fork_guard();
assert_eq!(rendezvous.rendezvous_timeout(Duration::from_millis(10)), Err(RendezvousTimeoutError::Timeout));
drop(guard);
Trait Implementations§
Source§impl Default for Rendezvous
impl Default for Rendezvous
Auto Trait Implementations§
impl Freeze for Rendezvous
impl RefUnwindSafe for Rendezvous
impl Send for Rendezvous
impl !Sync for Rendezvous
impl Unpin for Rendezvous
impl UnwindSafe for Rendezvous
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more