flexible_locks/
lib.rs

1// Copyright 2018 Mike Hommey
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! # Flexible Locks
10//!
11//! This crate aims at providing generic, flexible implementations of locking
12//! primitives. For now, it only provides `Mutex` types (i.e. no `RwLock`, etc.),
13//! without [poisoning], and without `try_lock`. Support for those can be
14//! added in the future if there is interest (patches welcome). Poisoning is not
15//! necessary with panic=abort.
16//!
17//! [poisoning]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#poisoning
18//!
19//! The provided types allow flexibility in layout and locking implementation.
20//! See the [`Mutex`], [`MutexWrap`] and [`RawOsMutex`] documentation for more
21//! details.
22//!
23//! # Features
24//!
25//! The `parking_lot` feature can be enabled, providing a [`RawMutex`]
26//! implementation for `parking_log::Mutex<()>`.
27#![no_std]
28#![deny(missing_docs)]
29
30#[cfg(any(feature = "std", test))]
31extern crate std;
32#[cfg(any(feature = "std", test))]
33use std::prelude::v1::*;
34
35#[cfg(windows)]
36extern crate winapi;
37
38#[cfg(unix)]
39extern crate libc;
40
41#[macro_use]
42extern crate flexible_locks_derive;
43
44#[cfg(feature = "allocator_api")]
45extern crate allocator_api;
46
47#[cfg(feature = "parking_lot")]
48extern crate parking_lot;
49
50// Public for the *_new macros.
51#[doc(hidden)]
52pub use core::cell::UnsafeCell;
53use core::marker::PhantomData;
54use core::ops::{Deref, DerefMut};
55use core::ptr;
56
57// For #[derive(MutexProtected)]
58mod flexible_locks {
59    pub use super::MutexProtected;
60}
61
62mod os;
63
64pub use os::*;
65
66/// A trait for raw mutual exclusion primitives.
67pub trait RawMutex: Send + Sync {
68    /// Initialize the raw mutex.
69    ///
70    /// Because initializing an instance may involve moving its location
71    /// when doing e.g. `Box::new(Foo::new())`, because some types
72    /// of raw mutex primitives need to be initialized at their final,
73    /// permanent location (e.g. [`CRITICAL_SECTION`]), or because some
74    /// may not be statically initialized to an entirely satisfying state
75    /// (e.g. [`pthread_mutex_t`], see [issue #33770]), this method is called
76    /// from [`Mutex::new`] to finish the raw mutex initialization.
77    ///
78    /// [`CRITICAL_SECTION`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx
79    /// [`pthread_mutex_t`]: http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_mutex_init.html
80    /// [issue #33770]: https://github.com/rust-lang/rust/issues/33770
81    unsafe fn init(&mut self) {}
82
83    /// Destroy the raw mutex.
84    ///
85    /// In some cases, raw mutex primitives need to be cleaned up after
86    /// use, so this method is called when a [`Mutex`] is dropped.
87    unsafe fn destroy(&self) {}
88
89    /// Acquire the raw mutex.
90    unsafe fn lock(&self);
91
92    /// Release the raw mutex.
93    unsafe fn unlock(&self);
94}
95
96/// Wrapping a `RawMutex` in a `Box` is just as good a valid `RawMutex`.
97///
98/// Ideally, any type that derefs to a `RawMutex` would be good too, but
99/// without specialization, this would prevent implementing `RawMutex` on
100/// your own mutex types.
101//
102// Ideally, this would be:
103// `impl<T: RawMutex, U: DerefMut<Target = T> + Send + Sync> RawMutex for U`
104#[cfg(any(feature = "std", test))]
105impl<T: RawMutex> RawMutex for Box<T> {
106    unsafe fn init(&mut self) {
107        self.as_mut().init()
108    }
109
110    unsafe fn lock(&self) {
111        self.as_ref().lock()
112    }
113
114    unsafe fn unlock(&self) {
115        self.as_ref().unlock()
116    }
117
118    unsafe fn destroy(&self) {
119        self.as_ref().destroy()
120    }
121}
122
123/// A trait describing types that can be wrapped in a [`Mutex`].
124///
125/// It is not recommended to implement this trait manually. Instead, use the
126/// `flexible-locks_derive` crate that provides a custom
127/// `#[derive(MutexProtected)]`.
128///
129/// When using that custom derive, the `#[mutex]` attribute is used to
130/// indicate the data field containing the raw mutex type.
131///
132/// # Examples
133///
134/// ```
135/// extern crate flexible_locks;
136/// #[macro_use]
137/// extern crate flexible_locks_derive;
138/// use flexible_locks::{Mutex, RawMutex};
139///
140/// // Pick your choice of raw mutex;
141/// #[cfg(windows)]
142/// use flexible_locks::CRITICAL_SECTION as RawOsMutex;
143/// #[cfg(unix)]
144/// use flexible_locks::pthread_mutex_t as RawOsMutex;
145///
146/// #[derive(MutexProtected)]
147/// struct Data {
148///     a: usize,
149///     #[mutex]
150///     mutex: RawOsMutex,
151///     b: usize,
152/// }
153/// # fn main() {}
154/// ```
155pub trait MutexProtected {
156    /// Raw mutex pritimive used to protect the data type.
157    type MutexType: RawMutex;
158
159    /// Data type that [`Mutex::lock`] will give access to.
160    ///
161    /// `[derive(MutexProtected)]` makes this `Self` when the type is large,
162    /// but when there are only two fields in the struct (whichever their
163    /// order is), it will set the `DataType` to the type of the non-mutex
164    /// field.
165    ///
166    /// # Examples
167    ///
168    /// ```
169    /// extern crate flexible_locks;
170    /// #[macro_use]
171    /// extern crate flexible_locks_derive;
172    /// use flexible_locks::{Mutex, RawMutex};
173    ///
174    /// // Pick your choice of raw mutex;
175    /// #[cfg(windows)]
176    /// use flexible_locks::SRWLOCK as RawOsMutex;
177    /// #[cfg(unix)]
178    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
179    ///
180    /// #[derive(MutexProtected, Default)]
181    /// struct Data {
182    ///     a: usize,
183    ///     b: usize,
184    ///     #[mutex]
185    ///     mutex: RawOsMutex,
186    /// }
187    ///
188    /// #[derive(MutexProtected, Default)]
189    /// struct Data2 {
190    ///     a: usize,
191    ///     #[mutex]
192    ///     mutex: RawOsMutex,
193    /// }
194    ///
195    /// #[derive(MutexProtected, Default)]
196    /// struct Data3 {
197    ///     #[mutex]
198    ///     mutex: RawOsMutex,
199    ///     a: usize,
200    /// }
201    ///
202    /// fn main() {
203    ///     let mut mutex = Mutex::new(Data::default());
204    ///     mutex.lock().a = 10;
205    ///     let mut mutex = Mutex::new(Data2::default());
206    ///     *mutex.lock() = 10;
207    ///     let mut mutex = Mutex::new(Data3::default());
208    ///     *mutex.lock() = 10;
209    /// }
210    /// ```
211    ///
212    /// `MutexWrap<RawOsMutex, usize>` should be preferred to `Mutex<Data2>`
213    /// and `Mutex<Data3>`.
214    type DataType: ?Sized;
215
216    /// Return an immutable reference to the raw mutex.
217    fn get_mutex(&self) -> &Self::MutexType;
218
219    /// Return a mutable reference to the raw mutex.
220    fn get_mutex_mut(&mut self) -> &mut Self::MutexType;
221
222    /// Return an immutable reference to the data.
223    fn get_data(&self) -> &Self::DataType;
224
225    /// Return a mutable reference to the data.
226    fn get_data_mut(&mut self) -> &mut Self::DataType;
227
228    /// Consumes the wrapping type, returning the underlying data.
229    fn into_data(self) -> Self::DataType
230    where
231        Self::DataType: Sized;
232}
233
234// FIXME: specialization should allow to just use (M, T) directly,
235// and to turn MutexWrap into a type alias.
236#[doc(hidden)]
237#[derive(MutexProtected)]
238pub struct MutexWrapper<M: RawMutex, T: ?Sized>(#[mutex] pub M, pub T);
239
240impl<M: RawMutex + Default, T> From<T> for MutexWrapper<M, T> {
241    fn from(t: T) -> Self {
242        MutexWrapper(Default::default(), t)
243    }
244}
245
246/// A mutual exclusion primitive useful for protecting shared data
247///
248/// This mutex will block threads waiting for the lock to become available. The
249/// mutex can be statically initialized via the [`mutex_new`] macro, or created
250/// via a [`new`] constructor. Each mutex has a type parameter which represents
251/// the data that it is protecting. The data can only be accessed through the
252/// RAII guards returned from [`lock`], which guarantees that the data is only
253/// ever accessed when the mutex is locked.
254///
255/// [`new`]: #method.new
256/// [`lock`]: #method.lock
257///
258/// # Differences from [`std::sync::Mutex`]
259///
260/// - No poisoning.
261/// - No `try_lock`.
262/// - The underlying raw mutex primitive can be of any kind, within a `Box` or
263///   not, as long as the [`RawMutex`] trait is implemented. Choose carefully.
264/// - The raw mutex primitive can be embedded anywhere in the data type. See
265///   the [`MutexWrap`] type for a variant that looks more like
266///   [`std::sync::Mutex`] but still allows to use a specific raw mutex
267///   primitive.
268/// - With care, this can allow to share data through FFI and contend on the
269///   same locks. See the `ffi-example` directory.
270///
271/// [`std::sync::Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
272/// [`RawMutex`]: trait.RawMutex.html
273///
274/// # Examples
275///
276/// ```
277/// extern crate flexible_locks;
278/// #[macro_use]
279/// extern crate flexible_locks_derive;
280/// use flexible_locks::{Mutex, RawMutex};
281///
282/// // Pick your choice of raw mutex;
283/// #[cfg(windows)]
284/// use flexible_locks::SRWLOCK as RawOsMutex;
285/// #[cfg(unix)]
286/// use flexible_locks::pthread_mutex_t as RawOsMutex;
287///
288/// use std::sync::Arc;
289/// use std::thread;
290/// use std::sync::mpsc::channel;
291///
292/// #[derive(MutexProtected, Default)]
293/// struct Data {
294///     a: usize,
295///     b: usize,
296///     #[mutex]
297///     mutex: RawOsMutex,
298/// }
299///
300/// const N: usize = 10;
301///
302/// fn main() {
303///     // Spawn a few threads to increment a shared variable (non-atomically),
304///     // and let the main thread know once all increments are done.
305///     //
306///     // Here we're using an Arc to share memory among threads, and the data
307///     // inside the Arc is protected with a mutex.
308///     let data = Arc::new(Mutex::new(Data::default()));
309///
310///     let (tx, rx) = channel();
311///     for _ in 0..N {
312///         let (data, tx) = (data.clone(), tx.clone());
313///         thread::spawn(move || {
314///             // The shared state can only be accessed once the lock is held.
315///             // Our non-atomic increment is safe because we're the only thread
316///             // which can access the shared state when the lock is held.
317///             let mut data = data.lock();
318///             data.a += 1;
319///             if data.a == N {
320///                 tx.send(()).unwrap();
321///             }
322///             // the lock is unlocked here when `data` goes out of scope.
323///         });
324///     }
325///     
326///     rx.recv().unwrap();
327/// }
328/// ```
329///
330/// Please note that `#[derive(MutexProtected)]` treats structs containing only
331/// two fields including the raw mutex differently, such that the data handed
332/// by [`Mutex::lock`] is the non-mutex field, rather than the whole data.
333/// In that case, it is preferable to use [`MutexWrap`] instead.
334/// See [`MutexProtected::DataType`].
335pub struct Mutex<T: MutexProtected + ?Sized> {
336    #[doc(hidden)]
337    pub __wrapper: UnsafeCell<T>,
338}
339
340unsafe impl<T: MutexProtected + ?Sized + Send> Send for Mutex<T> {}
341unsafe impl<T: MutexProtected + ?Sized + Send> Sync for Mutex<T> {}
342
343/// Statically initializes a [`Mutex`] or a [`MutexWrap`].
344///
345/// This skips the [`RawMutex::init`] method, so please be careful when using
346/// this, and ensure the statically initialized raw mutex is properly usable.
347///
348/// For non-static initialization, it is recommended to use [`Mutex::new`] or
349/// [`MutexWrap::new`].
350///
351/// # Examples
352///
353/// ```
354/// #[macro_use]
355/// extern crate flexible_locks;
356/// #[macro_use]
357/// extern crate flexible_locks_derive;
358/// use flexible_locks::{Mutex, MutexWrap, RawMutex};
359///
360/// // Pick your choice of raw mutex;
361/// #[cfg(windows)]
362/// use flexible_locks::SRWLOCK as RawOsMutex;
363/// #[cfg(unix)]
364/// use flexible_locks::pthread_mutex_t as RawOsMutex;
365///
366/// #[derive(MutexProtected)]
367/// struct Data {
368///     a: usize,
369///     b: usize,
370///     #[mutex]
371///     mutex: RawOsMutex,
372/// }
373///
374/// static DATA: Mutex<Data> = mutex_new!(Data {
375///     a: 2,
376///     b: 1,
377///     #[cfg(windows)]
378///     mutex: srwlock_new!(),
379///     #[cfg(unix)]
380///     mutex: pthread_mutex_new!(),
381/// });
382///
383/// struct Data2 {
384///     a: usize,
385///     b: usize,
386/// }
387///
388/// #[cfg(windows)]
389/// macro_rules! raw_os_mutex {
390///     () => { srwlock_new!() };
391/// }
392/// #[cfg(unix)]
393/// macro_rules! raw_os_mutex {
394///     () => { pthread_mutex_new!() };
395/// }
396///
397/// static DATA2: MutexWrap<RawOsMutex, Data2> = mutex_new!(
398///     raw_os_mutex!(),
399///     Data2 { a: 2, b: 1 }
400/// );
401/// # fn main() {}
402/// ```
403#[macro_export]
404macro_rules! mutex_new {
405    ($m:expr, $d:expr) => {
406        $crate::MutexWrap {
407            __inner: mutex_new!($crate::MutexWrapper($m, $d)),
408        }
409    };
410    ($e:expr) => {
411        $crate::Mutex {
412            __wrapper: $crate::UnsafeCell::new($e),
413        }
414    };
415}
416
417impl<T: MutexProtected> Mutex<T>
418where
419    T::DataType: Sized,
420{
421    /// Creates a new mutex in an unlocked state ready for use.
422    ///
423    /// # Examples
424    ///
425    /// ```
426    /// #[macro_use]
427    /// extern crate flexible_locks;
428    /// #[macro_use]
429    /// extern crate flexible_locks_derive;
430    /// use flexible_locks::{Mutex, RawMutex};
431    ///
432    /// // Pick your choice of raw mutex;
433    /// #[cfg(windows)]
434    /// use flexible_locks::SRWLOCK as RawOsMutex;
435    /// #[cfg(unix)]
436    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
437    ///
438    /// #[derive(MutexProtected)]
439    /// struct Data {
440    ///     a: usize,
441    ///     b: usize,
442    ///     #[mutex]
443    ///     mutex: RawOsMutex,
444    /// }
445    ///
446    /// fn main() {
447    ///     let mutex = Mutex::new(Data {
448    ///         a: 2,
449    ///         b: 1,
450    ///         mutex: Default::default(),
451    ///     });
452    /// }
453    /// ```
454    pub fn new(t: T) -> Self {
455        let m = mutex_new!(t);
456        unsafe {
457            let wrapper: &mut T = &mut *m.__wrapper.get();
458            wrapper.get_mutex_mut().init();
459        }
460        m
461    }
462
463    /// Consumes this mutex, returning the underlying data.
464    ///
465    /// When the data type contains the raw mutex, which happens with
466    /// `#[derive(MutexProtected)]`, the returned data obviously still
467    /// contains it. It is however in a destroyed state and may not be
468    /// reused.
469    ///
470    /// # Examples
471    ///
472    /// ```
473    /// #[macro_use]
474    /// extern crate flexible_locks;
475    /// #[macro_use]
476    /// extern crate flexible_locks_derive;
477    /// use flexible_locks::{Mutex, RawMutex};
478    ///
479    /// // Pick your choice of raw mutex;
480    /// #[cfg(windows)]
481    /// use flexible_locks::SRWLOCK as RawOsMutex;
482    /// #[cfg(unix)]
483    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
484    ///
485    /// #[derive(MutexProtected)]
486    /// struct Data {
487    ///     a: usize,
488    ///     b: usize,
489    ///     #[mutex]
490    ///     mutex: RawOsMutex,
491    /// }
492    ///
493    /// fn main() {
494    ///     let mutex = Mutex::new(Data {
495    ///         a: 2,
496    ///         b: 1,
497    ///         mutex: Default::default(),
498    ///     });
499    ///     let data = mutex.into_inner();
500    ///     assert_eq!(data.a, 2);
501    ///     assert_eq!(data.b, 1);
502    /// }
503    /// ```
504    pub fn into_inner(self) -> T::DataType {
505        unsafe {
506            let wrapper = ptr::read(&self.__wrapper);
507            core::mem::forget(self);
508            wrapper.into_inner().into_data()
509        }
510    }
511}
512
513impl<T: MutexProtected> From<T> for Mutex<T>
514where
515    T::DataType: Sized,
516{
517    fn from(t: T) -> Self {
518        Mutex::<T>::new(t)
519    }
520}
521
522impl<T: MutexProtected<DataType = T> + Sized + Default> Default for Mutex<T> {
523    fn default() -> Self {
524        Mutex::<T>::new(Default::default())
525    }
526}
527
528impl<T: MutexProtected + ?Sized> Mutex<T> {
529    /// Acquires a mutex, blocking the current thread until it is able to do so.
530    ///
531    /// This function will block the local thread until it is available to acquire
532    /// the mutex. Upon returning, the thread is the only thread with the lock
533    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
534    /// the guard goes out of scope, the mutex will be unlocked.
535    ///
536    /// The exact behavior on locking a mutex in the thread which already holds
537    /// the lock depends on the underlying raw mutex implementation.
538    ///
539    /// # Examples
540    ///
541    /// ```
542    /// extern crate flexible_locks;
543    /// #[macro_use]
544    /// extern crate flexible_locks_derive;
545    /// use flexible_locks::{Mutex, RawMutex};
546    ///
547    /// // Pick your choice of raw mutex;
548    /// #[cfg(windows)]
549    /// use flexible_locks::SRWLOCK as RawOsMutex;
550    /// #[cfg(unix)]
551    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
552    ///
553    /// use std::sync::Arc;
554    /// use std::thread;
555    ///
556    /// #[derive(MutexProtected, Default)]
557    /// struct Data {
558    ///     a: usize,
559    ///     b: usize,
560    ///     #[mutex]
561    ///     mutex: RawOsMutex,
562    /// }
563    ///
564    /// fn main() {
565    ///     let mutex = Arc::new(Mutex::new(Data::default()));
566    ///     let c_mutex = mutex.clone();
567    ///
568    ///     thread::spawn(move || {
569    ///         c_mutex.lock().a = 10;
570    ///     }).join().expect("thread::spawn failed");
571    ///     assert_eq!(mutex.lock().a, 10);
572    /// }
573    /// ```
574    pub fn lock(&self) -> MutexGuard<T> {
575        unsafe {
576            let wrapper = &mut *self.__wrapper.get();
577            wrapper.get_mutex().lock();
578            MutexGuard::new(wrapper)
579        }
580    }
581
582    /// Returns a mutable reference to the underlying data.
583    ///
584    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
585    /// take place---the mutable borrow statically guarantees no locks exist.
586    ///
587    /// # Examples
588    ///
589    /// ```
590    /// extern crate flexible_locks;
591    /// #[macro_use]
592    /// extern crate flexible_locks_derive;
593    /// use flexible_locks::{Mutex, RawMutex};
594    ///
595    /// // Pick your choice of raw mutex;
596    /// #[cfg(windows)]
597    /// use flexible_locks::SRWLOCK as RawOsMutex;
598    /// #[cfg(unix)]
599    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
600    ///
601    /// #[derive(MutexProtected, Default)]
602    /// struct Data {
603    ///     a: usize,
604    ///     b: usize,
605    ///     #[mutex]
606    ///     mutex: RawOsMutex,
607    /// }
608    ///
609    /// fn main() {
610    ///     let mut mutex = Mutex::new(Data::default());
611    ///     mutex.get_mut().a = 10;
612    ///     assert_eq!(mutex.lock().a, 10);
613    /// }
614    /// ```
615    pub fn get_mut(&mut self) -> &mut T::DataType {
616        let wrapper = unsafe { &mut *self.__wrapper.get() };
617        T::get_data_mut(wrapper)
618    }
619}
620
621impl<T: MutexProtected + ?Sized> Drop for Mutex<T> {
622    fn drop(&mut self) {
623        unsafe {
624            let wrapper: &T = &*self.__wrapper.get();
625            wrapper.get_mutex().destroy();
626        }
627    }
628}
629
630/// A mutual exclusion primitive useful for protecting shared data
631///
632/// This mutex will block threads waiting for the lock to become available. The
633/// mutex can be statically initialized via the [`mutex_new`] macro, or created
634/// via a [`new`] constructor. Each mutex has a raw mutex and a type parameter
635/// which represents the data that it is protecting. The data can only be
636/// accessed through the RAII guards returned from [`lock`], which guarantees
637/// that the data is only ever accessed when the mutex is locked.
638///
639/// [`new`]: #method.new
640/// [`lock`]: #method.lock
641///
642/// # Differences from [`std::sync::Mutex`]
643///
644/// - No poisoning.
645/// - No `try_lock`.
646/// - The underlying raw mutex primitive can be of any kind, within a `Box` or
647///   not, as long as the [`RawMutex`] trait is implemented. Choose carefully.
648/// - With care, this can allow to share data through FFI and contend on the
649///   same locks. See the `ffi-example` directory.
650///
651/// # Examples
652///
653/// ```
654/// extern crate flexible_locks;
655/// #[macro_use]
656/// extern crate flexible_locks_derive;
657/// use flexible_locks::MutexWrap;
658///
659/// // Pick your choice of raw mutex;
660/// #[cfg(windows)]
661/// use flexible_locks::SRWLOCK as RawOsMutex;
662/// #[cfg(unix)]
663/// use flexible_locks::pthread_mutex_t as RawOsMutex;
664///
665/// use std::sync::Arc;
666/// use std::thread;
667/// use std::sync::mpsc::channel;
668///
669/// const N: usize = 10;
670///
671/// fn main() {
672///     // Spawn a few threads to increment a shared variable (non-atomically),
673///     // and let the main thread know once all increments are done.
674///     //
675///     // Here we're using an Arc to share memory among threads, and the data
676///     // inside the Arc is protected with a mutex.
677///     let data = Arc::new(MutexWrap::<RawOsMutex, _>::new(0));
678///
679///     let (tx, rx) = channel();
680///     for _ in 0..N {
681///         let (data, tx) = (data.clone(), tx.clone());
682///         thread::spawn(move || {
683///             // The shared state can only be accessed once the lock is held.
684///             // Our non-atomic increment is safe because we're the only thread
685///             // which can access the shared state when the lock is held.
686///             let mut data = data.lock();
687///             *data += 1;
688///             if *data == N {
689///                 tx.send(()).unwrap();
690///             }
691///             // the lock is unlocked here when `data` goes out of scope.
692///         });
693///     }
694///     
695///     rx.recv().unwrap();
696/// }
697/// ```
698pub struct MutexWrap<M: RawMutex, T: ?Sized> {
699    #[doc(hidden)]
700    pub __inner: Mutex<MutexWrapper<M, T>>,
701}
702
703impl<M: RawMutex + Default, T> MutexWrap<M, T> {
704    /// Creates a new mutex in an unlocked state ready for use.
705    ///
706    /// # Examples
707    ///
708    /// ```
709    /// #[macro_use]
710    /// extern crate flexible_locks;
711    /// #[macro_use]
712    /// extern crate flexible_locks_derive;
713    /// use flexible_locks::MutexWrap;
714    ///
715    /// // Pick your choice of raw mutex;
716    /// #[cfg(windows)]
717    /// use flexible_locks::SRWLOCK as RawOsMutex;
718    /// #[cfg(unix)]
719    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
720    ///
721    /// fn main() {
722    ///     let mutex = MutexWrap::<RawOsMutex, _>::new(0);
723    /// }
724    /// ```
725    pub fn new(t: T) -> Self {
726        MutexWrap {
727            __inner: Mutex::new(MutexWrapper(Default::default(), t)),
728        }
729    }
730
731    /// Consumes this mutex, returning the underlying data.
732    ///
733    /// # Examples
734    ///
735    /// ```
736    /// #[macro_use]
737    /// extern crate flexible_locks;
738    /// #[macro_use]
739    /// extern crate flexible_locks_derive;
740    /// use flexible_locks::MutexWrap;
741    ///
742    /// // Pick your choice of raw mutex;
743    /// #[cfg(windows)]
744    /// use flexible_locks::SRWLOCK as RawOsMutex;
745    /// #[cfg(unix)]
746    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
747    ///
748    /// fn main() {
749    ///     let mutex = MutexWrap::<RawOsMutex, _>::new(0);
750    ///     assert_eq!(mutex.into_inner(), 0);
751    /// }
752    /// ```
753    pub fn into_inner(self) -> T {
754        self.__inner.into_inner()
755    }
756}
757
758impl<M: RawMutex + Default, T> From<T> for MutexWrap<M, T> {
759    fn from(t: T) -> Self {
760        MutexWrap::new(t)
761    }
762}
763
764impl<M: RawMutex + Default, T: Default> Default for MutexWrap<M, T> {
765    fn default() -> Self {
766        MutexWrap::new(Default::default())
767    }
768}
769
770impl<M: RawMutex, T: ?Sized> MutexWrap<M, T> {
771    /// Acquires a mutex, blocking the current thread until it is able to do so.
772    ///
773    /// This function will block the local thread until it is available to acquire
774    /// the mutex. Upon returning, the thread is the only thread with the lock
775    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
776    /// the guard goes out of scope, the mutex will be unlocked.
777    ///
778    /// The exact behavior on locking a mutex in the thread which already holds
779    /// the lock depends on the underlying raw mutex implementation.
780    ///
781    /// # Examples
782    ///
783    /// ```
784    /// extern crate flexible_locks;
785    /// #[macro_use]
786    /// extern crate flexible_locks_derive;
787    /// use flexible_locks::MutexWrap;
788    ///
789    /// // Pick your choice of raw mutex;
790    /// #[cfg(windows)]
791    /// use flexible_locks::SRWLOCK as RawOsMutex;
792    /// #[cfg(unix)]
793    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
794    ///
795    /// use std::sync::Arc;
796    /// use std::thread;
797    ///
798    /// fn main() {
799    ///     let mutex = Arc::new(MutexWrap::<RawOsMutex, _>::new(0));
800    ///     let c_mutex = mutex.clone();
801    ///
802    ///     thread::spawn(move || {
803    ///         *c_mutex.lock() = 10;
804    ///     }).join().expect("thread::spawn failed");
805    ///     assert_eq!(*mutex.lock(), 10);
806    /// }
807    /// ```
808    pub fn lock(&self) -> MutexGuard<MutexWrapper<M, T>> {
809        self.__inner.lock()
810    }
811
812    /// Returns a mutable reference to the underlying data.
813    ///
814    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
815    /// take place---the mutable borrow statically guarantees no locks exist.
816    ///
817    /// # Examples
818    ///
819    /// ```
820    /// extern crate flexible_locks;
821    /// #[macro_use]
822    /// extern crate flexible_locks_derive;
823    /// use flexible_locks::MutexWrap;
824    ///
825    /// // Pick your choice of raw mutex;
826    /// #[cfg(windows)]
827    /// use flexible_locks::SRWLOCK as RawOsMutex;
828    /// #[cfg(unix)]
829    /// use flexible_locks::pthread_mutex_t as RawOsMutex;
830    ///
831    /// fn main() {
832    ///     let mut mutex = MutexWrap::<RawOsMutex, _>::new(0);
833    ///     *mutex.get_mut() = 10;
834    ///     assert_eq!(*mutex.lock(), 10);
835    /// }
836    /// ```
837    pub fn get_mut(&mut self) -> &mut T {
838        self.__inner.get_mut()
839    }
840}
841
842/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
843/// dropped (falls out of scope), the lock will be unlocked.
844///
845/// The data protected by the mutex can be accessed through this guard via its
846/// [`Deref`] and [`DerefMut`] implementations.
847///
848/// This structure is created by [`Mutex::lock`] and [`MutexWrap::lock`].
849#[must_use]
850pub struct MutexGuard<'a, T: MutexProtected + ?Sized + 'a> {
851    __wrapper: &'a mut T,
852    marker: PhantomData<*mut ()>, // prevents an automatic impl Send.
853}
854
855unsafe impl<'a, T: MutexProtected + ?Sized + Sync> Sync for MutexGuard<'a, T> {}
856
857impl<'a, T: MutexProtected + ?Sized + 'a> MutexGuard<'a, T> {
858    fn new(wrapper: &'a mut T) -> Self {
859        MutexGuard {
860            __wrapper: wrapper,
861            marker: PhantomData,
862        }
863    }
864}
865
866impl<'a, T: MutexProtected + ?Sized + 'a> Drop for MutexGuard<'a, T> {
867    fn drop(&mut self) {
868        unsafe {
869            self.__wrapper.get_mutex().unlock();
870        }
871    }
872}
873
874impl<'a, T: MutexProtected + ?Sized + 'a> Deref for MutexGuard<'a, T> {
875    type Target = T::DataType;
876
877    fn deref(&self) -> &T::DataType {
878        T::get_data(&self.__wrapper)
879    }
880}
881
882impl<'a, T: MutexProtected + ?Sized + 'a> DerefMut for MutexGuard<'a, T> {
883    fn deref_mut(&mut self) -> &mut T::DataType {
884        T::get_data_mut(&mut self.__wrapper)
885    }
886}
887
888/// Type alias for `parking_lot::Mutex<()>`.
889#[cfg(feature = "parking_lot")]
890pub type ParkingLotMutex = parking_lot::Mutex<()>;
891
892#[cfg(feature = "parking_lot")]
893impl RawMutex for ParkingLotMutex {
894    unsafe fn lock(&self) {
895        self.raw_lock()
896    }
897
898    unsafe fn unlock(&self) {
899        self.raw_unlock()
900    }
901}
902
903#[cfg(test)]
904mod tests {
905    use super::*;
906    #[cfg(windows)]
907    type RawOsMutex = SRWLOCK;
908    #[cfg(unix)]
909    type RawOsMutex = pthread_mutex_t;
910
911    mod base {
912        use super::*;
913
914        static mut INITIALIZED: usize = 0;
915        static mut LOCKED: usize = 0;
916        static mut UNLOCKED: usize = 0;
917        static mut DESTROYED: usize = 0;
918
919        #[derive(PartialEq, Debug, Default)]
920        struct FakeMutex;
921
922        unsafe impl Send for FakeMutex {}
923        unsafe impl Sync for FakeMutex {}
924
925        impl RawMutex for FakeMutex {
926            unsafe fn init(&mut self) {
927                INITIALIZED += 1;
928            }
929
930            unsafe fn lock(&self) {
931                LOCKED += 1;
932            }
933
934            unsafe fn unlock(&self) {
935                UNLOCKED += 1;
936            }
937
938            unsafe fn destroy(&self) {
939                DESTROYED += 1;
940            }
941        }
942
943        #[derive(MutexProtected, PartialEq, Debug, Default)]
944        struct WithEmbeddedMutex<M: RawMutex>(usize, #[mutex] M, usize);
945
946        #[test]
947        fn smoke() {
948            macro_rules! smoke_test {
949                ($m:expr, $drop:expr) => {
950                    unsafe {
951                        INITIALIZED = 0;
952                        LOCKED = 0;
953                        UNLOCKED = 0;
954                        DESTROYED = 0;
955                    }
956                    let m = $m;
957                    unsafe {
958                        assert_eq!(INITIALIZED, 1);
959                        assert_eq!(LOCKED, 0);
960                        assert_eq!(UNLOCKED, 0);
961                        assert_eq!(DESTROYED, 0);
962                    }
963                    for i in 0..2 {
964                        let data = m.lock();
965                        unsafe {
966                            assert_eq!(INITIALIZED, 1);
967                            assert_eq!(LOCKED, i + 1);
968                            assert_eq!(UNLOCKED, i);
969                            assert_eq!(DESTROYED, 0);
970                        }
971                        drop(data);
972                        unsafe {
973                            assert_eq!(INITIALIZED, 1);
974                            assert_eq!(LOCKED, i + 1);
975                            assert_eq!(UNLOCKED, i + 1);
976                            assert_eq!(DESTROYED, 0);
977                        }
978                    }
979                    $drop(m);
980                    unsafe {
981                        assert_eq!(INITIALIZED, 1);
982                        assert_eq!(LOCKED, 2);
983                        assert_eq!(UNLOCKED, 2);
984                        assert_eq!(DESTROYED, 1);
985                    }
986                };
987            }
988
989            smoke_test!(MutexWrap::<FakeMutex, usize>::new(42), drop);
990            smoke_test!(
991                MutexWrap::<FakeMutex, usize>::new(42),
992                |m: MutexWrap<_, _>| assert_eq!(m.into_inner(), 42)
993            );
994            smoke_test!(MutexWrap::<Box<FakeMutex>, usize>::new(42), drop);
995            smoke_test!(
996                MutexWrap::<Box<FakeMutex>, usize>::new(42),
997                |m: MutexWrap<_, _>| assert_eq!(m.into_inner(), 42)
998            );
999            smoke_test!(Mutex::new(WithEmbeddedMutex(42, FakeMutex, 42)), drop);
1000            smoke_test!(
1001                Mutex::new(WithEmbeddedMutex(42, FakeMutex, 42)),
1002                |m: Mutex<_>| assert_eq!(m.into_inner(), WithEmbeddedMutex(42, FakeMutex, 42))
1003            );
1004            smoke_test!(
1005                Mutex::new(WithEmbeddedMutex(42, Box::new(FakeMutex), 42)),
1006                drop
1007            );
1008            smoke_test!(
1009                Mutex::new(WithEmbeddedMutex(42, Box::new(FakeMutex), 42)),
1010                |m: Mutex<_>| assert_eq!(
1011                    m.into_inner(),
1012                    WithEmbeddedMutex(42, Box::new(FakeMutex), 42)
1013                )
1014            );
1015        }
1016    }
1017
1018    mod wrap {
1019        use super::*;
1020        type Mutex<T> = super::MutexWrap<RawOsMutex, T>;
1021        include!("tests.rs");
1022    }
1023
1024    mod boxed {
1025        use super::*;
1026        type Mutex<T> = super::MutexWrap<Box<RawOsMutex>, T>;
1027        include!("tests.rs");
1028    }
1029
1030    #[cfg(feature = "parking_lot")]
1031    mod parking_lot {
1032        use super::*;
1033        type Mutex<T> = super::MutexWrap<ParkingLotMutex, T>;
1034        include!("tests.rs");
1035    }
1036
1037    #[cfg(windows)]
1038    mod critical_section {
1039        use super::*;
1040        type Mutex<T> = super::MutexWrap<CRITICAL_SECTION, T>;
1041        include!("tests.rs");
1042    }
1043
1044    #[cfg(any(target_os = "macos", target_os = "ios"))]
1045    mod osspinlock {
1046        use super::*;
1047        type Mutex<T> = super::MutexWrap<OSSpinLock, T>;
1048        include!("tests.rs");
1049    }
1050}