Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/common/sync/src/mutex.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
//! Mutex type whose methods panic rather than returning error in case of
6
//! poison.
7
//!
8
//! The Mutex type in this module wraps the standard library Mutex and mirrors
9
//! the same methods, except that they panic where the standard library would
10
//! return a PoisonError. This API codifies our error handling strategy around
11
//! poisoned mutexes in crosvm.
12
//!
13
//! - Crosvm releases are built with panic=abort so poisoning never occurs. A panic while a mutex is
14
//! held (or ever) takes down the entire process. Thus we would like for code not to have to
15
//! consider the possibility of poison.
16
//!
17
//! - We could ask developers to always write `.lock().unwrap()` on a standard library mutex.
18
//! However, we would like to stigmatize the use of unwrap. It is confusing to permit unwrap but
19
//! only on mutex lock results. During code review it may not always be obvious whether a
20
//! particular unwrap is unwrapping a mutex lock result or a different error that should be
21
//! handled in a more principled way.
22
//!
23
//! Developers should feel free to use sync::Mutex anywhere in crosvm that they
24
//! would otherwise be using std::sync::Mutex.
25
26
use std::fmt;
27
use std::fmt::Debug;
28
use std::fmt::Display;
29
use std::sync::Mutex as StdMutex;
30
use std::sync::MutexGuard;
31
use std::sync::TryLockError;
32
33
/// A mutual exclusion primitive useful for protecting shared data.
34
#[derive(Default)]
35
pub struct Mutex<T: ?Sized> {
36
std: StdMutex<T>,
37
}
38
39
impl<T> Mutex<T> {
40
/// Creates a new mutex in an unlocked state ready for use.
41
pub const fn new(value: T) -> Mutex<T> {
42
Mutex {
43
std: StdMutex::new(value),
44
}
45
}
46
47
/// Consumes this mutex, returning the underlying data.
48
pub fn into_inner(self) -> T {
49
match self.std.into_inner() {
50
Ok(value) => value,
51
Err(_) => panic!("mutex is poisoned"),
52
}
53
}
54
}
55
56
impl<T: ?Sized> Mutex<T> {
57
/// Acquires a mutex, blocking the current thread until it is able to do so.
58
///
59
/// This function will block the local thread until it is available to
60
/// acquire the mutex. Upon returning, the thread is the only thread with
61
/// the lock held. An RAII guard is returned to allow scoped unlock of the
62
/// lock. When the guard goes out of scope, the mutex will be unlocked.
63
pub fn lock(&self) -> MutexGuard<T> {
64
match self.std.lock() {
65
Ok(guard) => guard,
66
Err(_) => panic!("mutex is poisoned"),
67
}
68
}
69
70
/// Attempts to acquire this lock.
71
///
72
/// If the lock could not be acquired at this time, then Err is returned.
73
/// Otherwise, an RAII guard is returned. The lock will be unlocked when the
74
/// guard is dropped.
75
///
76
/// This function does not block.
77
pub fn try_lock(&self) -> Result<MutexGuard<T>, WouldBlock> {
78
match self.std.try_lock() {
79
Ok(guard) => Ok(guard),
80
Err(TryLockError::Poisoned(_)) => panic!("mutex is poisoned"),
81
Err(TryLockError::WouldBlock) => Err(WouldBlock),
82
}
83
}
84
85
/// Returns a mutable reference to the underlying data.
86
///
87
/// Since this call borrows the Mutex mutably, no actual locking needs to
88
/// take place -- the mutable borrow statically guarantees no locks exist.
89
pub fn get_mut(&mut self) -> &mut T {
90
match self.std.get_mut() {
91
Ok(value) => value,
92
Err(_) => panic!("mutex is poisoned"),
93
}
94
}
95
}
96
97
impl<T> From<T> for Mutex<T> {
98
fn from(value: T) -> Self {
99
Mutex {
100
std: StdMutex::from(value),
101
}
102
}
103
}
104
105
impl<T: ?Sized + Debug> Debug for Mutex<T> {
106
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
107
Debug::fmt(&self.std, formatter)
108
}
109
}
110
111
/// The lock could not be acquired at this time because the operation would
112
/// otherwise block.
113
///
114
/// Error returned by Mutex::try_lock.
115
#[derive(Debug)]
116
pub struct WouldBlock;
117
118
impl Display for WouldBlock {
119
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
120
Display::fmt(&TryLockError::WouldBlock::<()>, formatter)
121
}
122
}
123
124
impl std::error::Error for WouldBlock {}
125
126