sublock/sync/
prooflock.rs

1//! A variant of RwLock with sublocks that can be opened at no cost by providing a proof that the
2//! main lock is opened.
3
4use std::cell::{ UnsafeCell };
5use std::marker::PhantomData;
6use std::sync::{ LockResult, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockResult };
7
8/// A trait specifying that a structure supports immutable borrowing if some proof is provided.
9pub trait ProofBorrow<P, T> {
10    fn borrow<'a>(&'a self, proof: &P) -> &'a T;
11}
12
13
14/// A trait specifying that a structure supports mutable borrowing if some proof is provided.
15pub trait ProofBorrowMut<P, T> {
16    fn borrow_mut<'a>(&'a self, proof: &P) -> &'a mut T;
17}
18
19pub struct SubCell<T> {
20    cell: UnsafeCell<T>,
21
22    // The owner has type BigLock<_> and has a unique key equal to `owner_key`.
23    owner_key: usize,
24}
25
26impl<T> SubCell<T> {
27    pub fn new<'a>(proof: &ProofMut<'a>, value: T) -> Self {
28        SubCell {
29            cell: UnsafeCell::new(value),
30            owner_key: proof.0,
31        }
32    }
33}
34
35impl<'b, T> ProofBorrow<Proof<'b>, T> for SubCell<T> {
36    fn borrow<'a>(&'a self, proof: &Proof<'b>) -> &'a T {
37        assert_eq!(self.owner_key, proof.0);
38        unsafe { &*self.cell.get() }
39    }
40}
41
42impl<'b, T> ProofBorrow<ProofMut<'b>, T> for SubCell<T> {
43    fn borrow<'a>(&'a self, proof: &ProofMut<'b>) -> &'a T {
44        assert_eq!(self.owner_key, proof.0);
45        unsafe { &*self.cell.get() }
46    }
47}
48
49impl<'b, T> ProofBorrowMut<ProofMut<'b>, T> for SubCell<T> {
50    fn borrow_mut<'a>(&'a self, proof: &ProofMut<'b>) -> &'a mut T {
51        assert_eq!(self.owner_key, proof.0);
52        unsafe { &mut *self.cell.get() }
53    }
54}
55
56/// With respect to Send and Sync, SubCell behaves as a RwLock.
57unsafe impl<T> Send for SubCell<T> where T: Send + Sync { }
58
59/// With respect to Send and Sync, SubCell behaves as a RwLock.
60unsafe impl<T> Sync for SubCell<T> where T: Send + Sync { }
61
62/// A proof that the MainLock is currently opened.
63/// Its lifetime is limited by that of the ReadGuard that provided it.
64pub struct Proof<'a>(usize, PhantomData<&'a()>);
65
66/// A proof that the MainLock is currently opened mutably.
67/// Its lifetime is limited by that of the WriteGuard that provided it.
68pub struct ProofMut<'a>(usize, PhantomData<&'a()>);
69
70pub type ReadGuard<'a, T> = (Proof<'a>, RwLockReadGuard<'a, T>);
71pub type WriteGuard<'a, T> = (ProofMut<'a>, RwLockWriteGuard<'a, T>);
72
73/// A variant of `RwLock` with sublocks that can be opened at no cost by providing a proof
74/// that the main lock is opened.
75///
76/// ```
77/// use sublock::sync::prooflock::*;
78/// use std::collections::HashMap;
79///
80/// type State = HashMap<usize, SubCell<usize>>;
81/// let data : MainLock<State> = MainLock::new(HashMap::new());
82///
83/// {
84///     println!("* Attempt to read in the MainLock.");
85///     let (_, guard) = data.read().unwrap();
86///     assert_eq!(guard.len(), 0);
87/// }
88///
89/// {
90///     println!("* Attempt to write in the MainLock.");
91///     let (proof, mut guard) = data.write().unwrap();
92///     guard.insert(0, SubCell::new(&proof, 42));
93///     assert_eq!(guard.len(), 1);
94/// }
95///
96/// {
97///     println!("* Attempt to read in a SubCell.");
98///     let (proof, guard) = data.read().unwrap();
99///     assert_eq!(guard.len(), 1);
100///     let cell = guard.get(&0).unwrap();
101///     assert_eq!(*cell.borrow(&proof), 42);
102/// }
103///
104/// {
105///     println!("* Attempt to read and write in a SubCell.");
106///     let (proof, guard) = data.write().unwrap();
107///     assert_eq!(guard.len(), 1);
108///     let cell = guard.get(&0).unwrap();
109///     assert_eq!(*cell.borrow(&proof), 42);
110///
111///     *cell.borrow_mut(&proof) = 99;
112///     assert_eq!(*cell.borrow(&proof), 99);
113/// }
114///
115/// {
116///     println!("* Check that the SubCell changes are kept.");
117///     let (proof, guard) = data.read().unwrap();
118///     assert_eq!(guard.len(), 1);
119///     let cell = guard.get(&0).unwrap();
120///     assert_eq!(*cell.borrow(&proof), 99);
121/// }
122/// ```
123pub struct MainLock<T> {
124    lock: RwLock<T>,
125    ownership: usize,
126}
127impl<T> MainLock<T> {
128    pub fn new(value: T) -> Self {
129        use std::mem;
130        let ownership : usize = unsafe { mem::transmute(&value as *const T) };
131        MainLock {
132            lock: RwLock::new(value),
133            ownership: ownership
134        }
135    }
136
137    // As `RwLock.read`.
138    pub fn read(&self) -> LockResult<ReadGuard<T>> {
139        let proof = Proof(self.ownership, PhantomData);
140        match self.lock.read() {
141            Ok(ok) => Ok((proof, ok)),
142            Err(err) => Err(PoisonError::new((proof, err.into_inner())))
143        }
144    }
145
146    // As `RwLock.try_read`.
147    pub fn try_read(&self) ->  TryLockResult<ReadGuard<T>> {
148        use std::sync::TryLockError::*;
149        let proof = Proof(self.ownership, PhantomData);
150        match self.lock.try_read() {
151            Ok(ok) => Ok((proof, ok)),
152            Err(WouldBlock) => Err(WouldBlock),
153            Err(Poisoned(err)) => Err(Poisoned(PoisonError::new((proof, err.into_inner()))))
154        }
155    }
156
157    // As `RwLock.write`.
158    pub fn write(&self) -> LockResult<WriteGuard<T>> {
159        let proof = ProofMut(self.ownership, PhantomData);
160        match self.lock.write() {
161            Ok(ok) => Ok((proof, ok)),
162            Err(err) => Err(PoisonError::new((proof, err.into_inner())))
163        }
164    }
165
166    // As `RwLock.try_write`.
167    pub fn try_write(&self) ->  TryLockResult<WriteGuard<T>> {
168        use std::sync::TryLockError::*;
169        let proof = ProofMut(self.ownership, PhantomData);
170        match self.lock.try_write() {
171            Ok(ok) => Ok((proof, ok)),
172            Err(WouldBlock) => Err(WouldBlock),
173            Err(Poisoned(err)) => Err(Poisoned(PoisonError::new((proof, err.into_inner()))))
174        }
175    }
176}
177