      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271

    #![doc(html_root_url = "https://docs.rs/try-lock/0.2.3")]
    #![deny(missing_docs)]
    #![deny(missing_debug_implementations)]
    #![deny(warnings)]
    #![cfg_attr(not(test), no_std)]

    //! A light-weight lock guarded by an atomic boolean.
    //!
    //! Most efficient when contention is low, acquiring the lock is a single
    //! atomic swap, and releasing it just 1 more atomic swap.
    //!
    //! # Example
    //!
    //! ```
    //! use std::sync::Arc;
    //! use try_lock::TryLock;
    //!
    //! // a thing we want to share
    //! struct Widget {
    //!     name: String,
    //! }
    //!
    //! // lock it up!
    //! let widget1 = Arc::new(TryLock::new(Widget {
    //!     name: "Spanner".into(),
    //! }));
    //!
    //! let widget2 = widget1.clone();
    //!
    //!
    //! // mutate the widget
    //! let mut locked = widget1.try_lock().expect("example isn't locked yet");
    //! locked.name.push_str(" Bundle");
    //!
    //! // hands off, buddy
    //! let not_locked = widget2.try_lock();
    //! assert!(not_locked.is_none(), "widget1 has the lock");
    //!
    //! // ok, you can have it
    //! drop(locked);
    //!
    //! let locked2 = widget2.try_lock().expect("widget1 lock is released");
    //!
    //! assert_eq!(locked2.name, "Spanner Bundle");
    //! ```

    #[cfg(test)]
    extern crate core;

    use core::cell::UnsafeCell;
    use core::fmt;
    use core::ops::{Deref, DerefMut};
    use core::sync::atomic::{AtomicBool, Ordering};

    /// A light-weight lock guarded by an atomic boolean.
    ///
    /// Most efficient when contention is low, acquiring the lock is a single
    /// atomic swap, and releasing it just 1 more atomic swap.
    ///
    /// It is only possible to try to acquire the lock, it is not possible to
    /// wait for the lock to become ready, like with a `Mutex`.
    #[derive(Default)]
    pub struct TryLock<T> {
        is_locked: AtomicBool,
        value: UnsafeCell<T>,
    }

    impl<T> TryLock<T> {
        /// Create a `TryLock` around the value.
        #[inline]
        pub fn new(val: T) -> TryLock<T> {
            TryLock {
                is_locked: AtomicBool::new(false),
                value: UnsafeCell::new(val),
            }
        }

        /// Try to acquire the lock of this value.
        ///
        /// If the lock is already acquired by someone else, this returns
        /// `None`. You can try to acquire again whenever you want, perhaps
        /// by spinning a few times, or by using some other means of
        /// notification.
        ///
        /// # Note
        ///
        /// The default memory ordering is to use `Acquire` to lock, and `Release`
        /// to unlock. If different ordering is required, use
        /// [`try_lock_explicit`](TryLock::try_lock_explicit) or
        /// [`try_lock_explicit_unchecked`](TryLock::try_lock_explicit_unchecked).
        #[inline]
        pub fn try_lock(&self) -> Option<Locked<T>> {
            unsafe {
                self.try_lock_explicit_unchecked(Ordering::Acquire, Ordering::Release)
            }
        }

        /// Try to acquire the lock of this value using the lock and unlock orderings.
        ///
        /// If the lock is already acquired by someone else, this returns
        /// `None`. You can try to acquire again whenever you want, perhaps
        /// by spinning a few times, or by using some other means of
        /// notification.
        #[inline]
        #[deprecated(
            since = "0.2.3",
            note = "This method is actually unsafe because it unsafely allows \
            the use of weaker memory ordering. Please use try_lock_explicit instead"
        )]
        pub fn try_lock_order(&self, lock_order: Ordering, unlock_order: Ordering) -> Option<Locked<T>> {
            unsafe {
                self.try_lock_explicit_unchecked(lock_order, unlock_order)
            }
        }

        /// Try to acquire the lock of this value using the specified lock and
        /// unlock orderings.
        ///
        /// If the lock is already acquired by someone else, this returns
        /// `None`. You can try to acquire again whenever you want, perhaps
        /// by spinning a few times, or by using some other means of
        /// notification.
        ///
        /// # Panic
        ///
        /// This method panics if `lock_order` is not any of `Acquire`, `AcqRel`,
        /// and `SeqCst`, or `unlock_order` is not any of `Release` and `SeqCst`.
        #[inline]
        pub fn try_lock_explicit(&self, lock_order: Ordering, unlock_order: Ordering) -> Option<Locked<T>> {
            match lock_order {
                Ordering::Acquire |
                Ordering::AcqRel |
                Ordering::SeqCst => {}
                _ => panic!("lock ordering must be `Acquire`, `AcqRel`, or `SeqCst`"),
            }

            match unlock_order {
                Ordering::Release |
                Ordering::SeqCst => {}
                _ => panic!("unlock ordering must be `Release` or `SeqCst`"),
            }

            unsafe {
                self.try_lock_explicit_unchecked(lock_order, unlock_order)
            }
        }

        /// Try to acquire the lock of this value using the specified lock and
        /// unlock orderings without checking that the specified orderings are
        /// strong enough to be safe.
        ///
        /// If the lock is already acquired by someone else, this returns
        /// `None`. You can try to acquire again whenever you want, perhaps
        /// by spinning a few times, or by using some other means of
        /// notification.
        ///
        /// # Safety
        ///
        /// Unlike [`try_lock_explicit`], this method is unsafe because it does not
        /// check that the given memory orderings are strong enough to prevent data
        /// race.
        ///
        /// [`try_lock_explicit`]: Self::try_lock_explicit
        #[inline]
        pub unsafe fn try_lock_explicit_unchecked(&self, lock_order: Ordering, unlock_order: Ordering) -> Option<Locked<T>> {
            if !self.is_locked.swap(true, lock_order) {
                Some(Locked {
                    lock: self,
                    order: unlock_order,
                })
            } else {
                None
            }
        }

        /// Take the value back out of the lock when this is the sole owner.
        #[inline]
        pub fn into_inner(self) -> T {
            debug_assert!(!self.is_locked.load(Ordering::Relaxed), "TryLock was mem::forgotten");
            // Since the compiler can statically determine this is the only owner,
            // it's safe to take the value out. In fact, in newer versions of Rust,
            // `UnsafeCell::into_inner` has been marked safe.
            //
            // To support older version (1.21), the unsafe block is still here.
            #[allow(unused_unsafe)]
            unsafe {
                self.value.into_inner()
            }
        }
    }

    unsafe impl<T: Send> Send for TryLock<T> {}
    unsafe impl<T: Send> Sync for TryLock<T> {}

    impl<T: fmt::Debug> fmt::Debug for TryLock<T> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

            // Used if the TryLock cannot acquire the lock.
            struct LockedPlaceholder;

            impl fmt::Debug for LockedPlaceholder {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    f.write_str("<locked>")
                }
            }

            let mut builder = f.debug_struct("TryLock");
            if let Some(locked) = self.try_lock() {
                builder.field("value", &*locked);
            } else {
                builder.field("value", &LockedPlaceholder);
            }
            builder.finish()
        }
    }

    /// A locked value acquired from a `TryLock`.
    ///
    /// The type represents an exclusive view at the underlying value. The lock is
    /// released when this type is dropped.
    ///
    /// This type derefs to the underlying value.
    #[must_use = "TryLock will immediately unlock if not used"]
    pub struct Locked<'a, T: 'a> {
        lock: &'a TryLock<T>,
        order: Ordering,
    }

    impl<'a, T> Deref for Locked<'a, T> {
        type Target = T;
        #[inline]
        fn deref(&self) -> &T {
            unsafe { &*self.lock.value.get() }
        }
    }

    impl<'a, T> DerefMut for Locked<'a, T> {
        #[inline]
        fn deref_mut(&mut self) -> &mut T {
            unsafe { &mut *self.lock.value.get() }
        }
    }

    impl<'a, T> Drop for Locked<'a, T> {
        #[inline]
        fn drop(&mut self) {
            self.lock.is_locked.store(false, self.order);
        }
    }

    impl<'a, T: fmt::Debug> fmt::Debug for Locked<'a, T> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            fmt::Debug::fmt(&**self, f)
        }
    }

    #[cfg(test)]
    mod tests {
        use super::TryLock;

        #[test]
        fn fmt_debug() {
            let lock = TryLock::new(5);
            assert_eq!(format!("{:?}", lock), "TryLock { value: 5 }");

            let locked = lock.try_lock().unwrap();
            assert_eq!(format!("{:?}", locked), "5");

            assert_eq!(format!("{:?}", lock), "TryLock { value: <locked> }");
        }
    }