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
// OwnedMutexGuard - Mutex guards that own the Mutex // Copyright (C) 2015 Jethro G. Beekman // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //! Mutex guards that own the Mutex. //! //! A standard `MutexGuard` requires the Mutex to live at least as long as the //! guard. This module contains a new guard type `OwnedMutexGuard`, which //! guarantees that an `OwnedMutex` stays alive until the guard is released, //! without any restrictions on the lifetime of the mutex. //! //! `Arc<Mutex<_>>`, `Rc<Mutex<_>>` and `Box<Mutex<_>>` implement `OwnedMutex`. //! //! The `OwnedMutex.owned_lock` function is used to create a new OwnedMutexGuard. //! //! ``` //! use std::sync::{Mutex,Arc}; //! use namedlock::lockresult::LockResult; //! use namedlock::ownedmutexguard::{OwnedMutex,OwnedMutexGuard}; //! //! // Note the return value has a lifetime distinct from the input //! fn get_locked<'a,T: Clone>(input: &T) -> LockResult<OwnedMutexGuard<'a,T,Arc<Mutex<T>>>> { //! Arc::new(Mutex::new(input.clone())).owned_lock() //! } //! //! assert_eq!([0,1,2,3,4,5,6,7,8,9],*get_locked(&[0,1,2,3,4,5,6,7,8,9]).unwrap()); //! ``` //! //! ## License //! OwnedMutexGuard - Copyright (C) 2015 Jethro G. Beekman //! //! This program is free software; you can redistribute it and/or //! modify it under the terms of the GNU General Public License //! as published by the Free Software Foundation; either version 2 //! of the License, or (at your option) any later version. //! //! This program is distributed in the hope that it will be useful, //! but WITHOUT ANY WARRANTY; without even the implied warranty of //! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //! GNU General Public License for more details. //! //! You should have received a copy of the GNU General Public License //! along with this program; if not, write to the Free Software Foundation, //! Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. use std::sync::{Mutex,MutexGuard}; use std::ops::{Deref,DerefMut}; use std; use lockresult::LockResult as Result; /// An RAII implementation of a "scoped lock" of a mutex. When this structure /// is dropped (falls out of scope), the lock will be unlocked, and the /// owner of the Mutex will be dropped. /// /// Alternatively, call `into_inner` to drop the guard and reclaim the owner. /// /// The data protected by the mutex can be accessed through this guard via its /// Deref and DerefMut implementations. pub struct OwnedMutexGuard<'a, T: 'a, M: OwnedMutex<T>> { owned_mutex: Option<M>, guard: Option<MutexGuard<'a,T>>, } impl<'a, T: 'a, M: OwnedMutex<T>> Deref for OwnedMutexGuard<'a,T,M> { type Target = T; fn deref<'b>(&'b self) -> &'b T { // This is always Some, because it's initialized as Some, and only drop() and into_inner() turn it into None match self.guard { Some(ref value) => &value, None => unreachable!(), // to be replace with std::intrinsics::unreachable once stable } } } impl<'a, T:'a, M: OwnedMutex<T>> DerefMut for OwnedMutexGuard<'a,T,M> { fn deref_mut<'b>(&'b mut self) -> &'b mut T { // This is always Some, because it's initialized as Some, and only drop() and into_inner() turn it into None match self.guard { Some(ref mut value) => unsafe{&mut*(value.deref_mut() as *mut _) as &'b mut T}, None => unreachable!(), // to be replace with std::intrinsics::unreachable once stable } } } impl<'a, T:'a, M: OwnedMutex<T>> Drop for OwnedMutexGuard<'a,T,M> { fn drop(&mut self) { self.guard=None; } } impl<'a, T: 'a, M: OwnedMutex<T>> OwnedMutexGuard<'a,T,M> { /// Drops the guard and returns the associated `OwnedMutex` pub fn into_inner(mut self) -> M { self.guard=None; // This is always Some, because it's initialized as Some, and only drop() or this turns it into None self.owned_mutex.take().unwrap() } } /// Implements the functions to obtain `OwnedMutexGuard`s. /// /// This trait must only be implemented for types for which the memory address /// of the value reachable via Deref remains identical even if self gets moved. pub unsafe trait OwnedMutex<T>: Sized + Deref<Target=Mutex<T>> { /// Acquires an `OwnedMutex`, blocking the current thread until it is able to do so. /// /// This function will block the local thread until it is available to acquire the mutex. /// Upon returning, the thread is the only thread with the mutex held. An RAII guard is /// returned to allow scoped unlock of the lock. When the guard goes out of scope, the /// mutex will be unlocked, and the OwnedMutex will be dropped. // Unsafety explanation: // The MutexGuard holds a reference to it's Mutex. As such, the mutex must stay alive // at that address until the guard drops. We guarantee this by storing the mutex // alongside the guard. // // In particular, we know that our reference to the mutex can be safely converted to // lifetime 'a since we will be storing the OwnedMutex in a structure with the same // lifetime 'a. fn owned_lock<'a>(self) -> Result<OwnedMutexGuard<'a,T,Self>> where Self: 'a { let guard=try!(unsafe{&*(&self as *const _) as &'a Mutex<T>}.lock()); return Ok(OwnedMutexGuard{owned_mutex:Some(self),guard:Some(guard)}); } } unsafe impl<T> OwnedMutex<T> for Box<Mutex<T>> {} unsafe impl<T> OwnedMutex<T> for std::rc::Rc<Mutex<T>> {} unsafe impl<T> OwnedMutex<T> for std::sync::Arc<Mutex<T>> {}