Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/common/sync/src/lib.rs
5394 views
1
// Copyright 2018 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
//! Sync primitive types whose methods panic rather than returning error in case of poison.
6
//!
7
//! The Mutex/Condvar type in this crates wraps the standard library versions and mirrors the same
8
//! methods, except that they panic where the standard library would return an Error. This API
9
//! codifies our error handling strategy around poisoned mutexes in crosvm.
10
//!
11
//! - Crosvm releases are built with panic=abort so poisoning never occurs. A panic while a mutex is
12
//! held (or ever) takes down the entire process. Thus we would like for code not to have to
13
//! consider the possibility of poison.
14
//!
15
//! - We could ask developers to always write `.lock().unwrap()` on a standard library mutex.
16
//! However, we would like to stigmatize the use of unwrap. It is confusing to permit unwrap but
17
//! only on mutex lock results. During code review it may not always be obvious whether a
18
//! particular unwrap is unwrapping a mutex lock result or a different error that should be
19
//! handled in a more principled way.
20
//!
21
//! Developers should feel free to use types defined in this crate anywhere in crosvm that they
22
//! would otherwise be using the corresponding types in std::sync.
23
24
mod condvar;
25
mod mutex;
26
27
use std::sync::Arc;
28
use std::sync::WaitTimeoutResult;
29
use std::time::Duration;
30
31
pub use crate::condvar::Condvar;
32
pub use crate::mutex::Mutex;
33
pub use crate::mutex::WouldBlock;
34
35
/// Waitable allows one thread to wait on a signal from another thread.
36
///
37
/// A Waitable is usually created with a Promise using
38
/// `create_promise_and_waitable`, and the Promise is used by one thread and the
39
/// Waitable can be used by another thread. Promise and Waitable do not use any
40
/// OS-level synchronization primitives.
41
pub struct Waitable(Arc<(Condvar, Mutex<bool>)>);
42
43
impl Waitable {
44
/// Return an already-signaled Waitable.
45
pub fn signaled() -> Self {
46
Waitable(Arc::new((Condvar::new(), Mutex::new(true))))
47
}
48
49
/// Perform a blocking wait on this Waitable.
50
pub fn wait(&self, timeout: Option<Duration>) -> WaitTimeoutResult {
51
let timeout = timeout.unwrap_or(Duration::MAX);
52
let (ref condvar, ref signaled_mutex) = *self.0;
53
condvar
54
.wait_timeout_while(signaled_mutex.lock(), timeout, |signaled| !*signaled)
55
.1
56
}
57
}
58
59
/// Promise allows one thread to signal a waitable that another thread can wait on.
60
pub struct Promise(Arc<(Condvar, Mutex<bool>)>);
61
62
impl Promise {
63
/// Signal this promise, and it's associated Waitable.
64
pub fn signal(&self) {
65
let (ref condvar, ref signaled_mutex) = *self.0;
66
*signaled_mutex.lock() = true;
67
condvar.notify_all();
68
}
69
}
70
71
/// Create a paired Promise and Waitable.
72
///
73
/// Signalling the Promise will signal the Waitable.
74
pub fn create_promise_and_waitable() -> (Promise, Waitable) {
75
let inner = Arc::new((Condvar::new(), Mutex::new(false)));
76
(Promise(Arc::clone(&inner)), Waitable(inner))
77
}
78
79