1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use sync
::atomic
::{AtomicBool, Ordering}
;
17 pub struct Flag { failed: AtomicBool }
19 // Note that the Ordering uses to access the `failed` field of `Flag` below is
20 // always `Relaxed`, and that's because this isn't actually protecting any data,
21 // it's just a flag whether we've panicked or not.
23 // The actual location that this matters is when a mutex is **locked** which is
24 // where we have external synchronization ensuring that we see memory
25 // reads/writes to this flag.
27 // As a result, if it matters, we should see the correct value for `failed` in
31 pub const fn new() -> Flag
{
32 Flag { failed: AtomicBool::new(false) }
36 pub fn borrow(&self) -> LockResult
<Guard
> {
37 let ret
= Guard { panicking: thread::panicking() }
;
39 Err(PoisonError
::new(ret
))
46 pub fn done(&self, guard
: &Guard
) {
47 if !guard
.panicking
&& thread
::panicking() {
48 self.failed
.store(true, Ordering
::Relaxed
);
53 pub fn get(&self) -> bool
{
54 self.failed
.load(Ordering
::Relaxed
)
62 /// A type of error which can be returned whenever a lock is acquired.
64 /// Both Mutexes and RwLocks are poisoned whenever a thread fails while the lock
65 /// is held. The precise semantics for when a lock is poisoned is documented on
66 /// each lock, but once a lock is poisoned then all future acquisitions will
67 /// return this error.
68 #[stable(feature = "rust1", since = "1.0.0")]
69 pub struct PoisonError
<T
> {
73 /// An enumeration of possible errors which can occur while calling the
74 /// `try_lock` method.
75 #[stable(feature = "rust1", since = "1.0.0")]
76 pub enum TryLockError
<T
> {
77 /// The lock could not be acquired because another thread failed while holding
79 #[stable(feature = "rust1", since = "1.0.0")]
80 Poisoned(#[stable(feature = "rust1", since = "1.0.0")] PoisonError<T>),
81 /// The lock could not be acquired at this time because the operation would
83 #[stable(feature = "rust1", since = "1.0.0")]
87 /// A type alias for the result of a lock method which can be poisoned.
89 /// The `Ok` variant of this result indicates that the primitive was not
90 /// poisoned, and the `Guard` is contained within. The `Err` variant indicates
91 /// that the primitive was poisoned. Note that the `Err` variant *also* carries
92 /// the associated guard, and it can be acquired through the `into_inner`
94 #[stable(feature = "rust1", since = "1.0.0")]
95 pub type LockResult
<Guard
> = Result
<Guard
, PoisonError
<Guard
>>;
97 /// A type alias for the result of a nonblocking locking method.
99 /// For more information, see `LockResult`. A `TryLockResult` doesn't
100 /// necessarily hold the associated guard in the `Err` type as the lock may not
101 /// have been acquired for other reasons.
102 #[stable(feature = "rust1", since = "1.0.0")]
103 pub type TryLockResult
<Guard
> = Result
<Guard
, TryLockError
<Guard
>>;
105 #[stable(feature = "rust1", since = "1.0.0")]
106 impl<T
> fmt
::Debug
for PoisonError
<T
> {
107 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
108 "PoisonError { inner: .. }".fmt(f
)
112 #[stable(feature = "rust1", since = "1.0.0")]
113 impl<T
> fmt
::Display
for PoisonError
<T
> {
114 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
115 "poisoned lock: another task failed inside".fmt(f
)
119 #[stable(feature = "rust1", since = "1.0.0")]
120 impl<T
: Reflect
> Error
for PoisonError
<T
> {
121 fn description(&self) -> &str {
122 "poisoned lock: another task failed inside"
126 impl<T
> PoisonError
<T
> {
127 /// Creates a `PoisonError`.
128 #[stable(feature = "sync_poison", since = "1.2.0")]
129 pub fn new(guard
: T
) -> PoisonError
<T
> {
130 PoisonError { guard: guard }
133 /// Consumes this error indicating that a lock is poisoned, returning the
134 /// underlying guard to allow access regardless.
135 #[stable(feature = "sync_poison", since = "1.2.0")]
136 pub fn into_inner(self) -> T { self.guard }
138 /// Reaches into this error indicating that a lock is poisoned, returning a
139 /// reference to the underlying guard to allow access regardless.
140 #[stable(feature = "sync_poison", since = "1.2.0")]
141 pub fn get_ref(&self) -> &T { &self.guard }
143 /// Reaches into this error indicating that a lock is poisoned, returning a
144 /// mutable reference to the underlying guard to allow access regardless.
145 #[stable(feature = "sync_poison", since = "1.2.0")]
146 pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
149 #[stable(feature = "rust1", since = "1.0.0")]
150 impl<T
> From
<PoisonError
<T
>> for TryLockError
<T
> {
151 fn from(err
: PoisonError
<T
>) -> TryLockError
<T
> {
152 TryLockError
::Poisoned(err
)
156 #[stable(feature = "rust1", since = "1.0.0")]
157 impl<T
> fmt
::Debug
for TryLockError
<T
> {
158 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
160 TryLockError
::Poisoned(..) => "Poisoned(..)".fmt(f
),
161 TryLockError
::WouldBlock
=> "WouldBlock".fmt(f
)
166 #[stable(feature = "rust1", since = "1.0.0")]
167 impl<T
> fmt
::Display
for TryLockError
<T
> {
168 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
170 TryLockError
::Poisoned(..) => "poisoned lock: another task failed inside",
171 TryLockError
::WouldBlock
=> "try_lock failed because the operation would block"
176 #[stable(feature = "rust1", since = "1.0.0")]
177 impl<T
: Reflect
> Error
for TryLockError
<T
> {
178 fn description(&self) -> &str {
180 TryLockError
::Poisoned(ref p
) => p
.description(),
181 TryLockError
::WouldBlock
=> "try_lock failed because the operation would block"
185 fn cause(&self) -> Option
<&Error
> {
187 TryLockError
::Poisoned(ref p
) => Some(p
),
193 pub fn map_result
<T
, U
, F
>(result
: LockResult
<T
>, f
: F
)
195 where F
: FnOnce(T
) -> U
{
198 Err(PoisonError { guard }
) => Err(PoisonError
::new(f(guard
)))