nitric_lock/
lib.rs

1#![deny(unused_must_use)]
2
3//! # `nitric-lock`
4//!
5
6pub use self::group::{LockGroup, LockToken};
7pub use self::join::lock2;
8pub use self::lock::{Lock, LockInfo, Mut, RawLockGuard, ReadLock, Ref, WriteLock};
9pub use self::mutex::{Mutex, MutexGuard};
10
11mod group;
12mod join;
13mod lock;
14mod mutex;
15
16// TODO: remove this code once the `join` mod is done
17/*
18pub struct MutexJoin<'a, A, B> {
19    head: &'a Mutex<A>,
20    tail: B,
21}
22
23impl<'a, A, B> MutexJoin<'a, A, B>
24where
25    B: 'a,
26{
27    pub fn new(head: &'a Mutex<A>, tail: B) -> Self {
28        MutexJoin { head, tail }
29    }
30
31    //noinspection RsNeedlessLifetimes
32    pub fn lock<'l>(&'l self) -> <Self as MutexLikeInner>::Output
33    where
34        B: MutexLikeInner<'l>,
35    {
36        let collection = self.collect_raw_set();
37
38        for (_, mutex) in collection {
39            mutex.lock();
40        }
41
42        unsafe { self.lock_unchecked() }
43    }
44
45    //noinspection RsNeedlessLifetimes
46    pub fn try_lock<'l>(&'l self) -> Option<<Self as MutexLikeInner<'_>>::Output>
47    where
48        B: MutexLikeInner<'l>,
49    {
50        let collection = self.collect_raw_set();
51
52        if collection.into_iter().map(|(_, m)| m.try_lock()).all(|b| b) {
53            unsafe { Some(self.lock_unchecked()) }
54        } else {
55            None
56        }
57    }
58
59    //noinspection RsNeedlessLifetimes
60    fn collect_raw_set<'l>(&'l self) -> Vec<(usize, &RawMutex)>
61    where
62        B: MutexLikeInner<'l>,
63    {
64        let mut collection = vec![];
65
66        unsafe {
67            self.extend_raw_set(&mut collection);
68        }
69
70        collection.sort_by_key(|e| e.0);
71
72        collection
73    }
74}
75
76impl<'a, A, B> MutexLikeInner<'a> for MutexJoin<'_, A, B>
77where
78    A: 'a,
79    B: MutexLikeInner<'a> + 'a,
80{
81    type Output = (MutexGuard<'a, A>, <B as MutexLikeInner<'a>>::Output);
82
83    unsafe fn extend_raw_set<E: Extend<(usize, &'a RawMutex)>>(&'a self, e: &mut E) {
84        self.head.extend_raw_set(e);
85        self.tail.extend_raw_set(e);
86    }
87
88    unsafe fn lock_unchecked(&'a self) -> <Self as MutexLikeInner<'a>>::Output {
89        (self.head.lock_unchecked(), self.tail.lock_unchecked())
90    }
91}
92
93pub trait MutexLike {}
94
95impl<T> MutexLike for T where T: for<'a> MutexLikeInner<'a> {}
96
97pub trait MutexLikeInner<'a> {
98    type Output;
99
100    unsafe fn extend_raw_set<E: Extend<(usize, &'a RawMutex)>>(&'a self, e: &mut E);
101    unsafe fn lock_unchecked(&'a self) -> Self::Output;
102}
103
104impl<'a, T> MutexLikeInner<'a> for &'a Mutex<T>
105where
106    T: 'a,
107{
108    type Output = MutexGuard<'a, T>;
109
110    unsafe fn extend_raw_set<E: Extend<(usize, &'a RawMutex)>>(&'a self, e: &mut E) {
111        e.extend(Some((self.lock_id(), self.raw())))
112    }
113
114    unsafe fn lock_unchecked(&'a self) -> <Self as MutexLikeInner<'a>>::Output {
115        self.acquire_guard()
116    }
117}
118
119#[macro_export]
120macro_rules! lock {
121    ($($ac:ident $id:ident),+) => {
122        lock!(lock => $($ac $id),*);
123    };
124    ($action:ident => $($ac:ident $id:ident),+) => {
125
126        {
127            let __join_binding;
128            __join_binding = lock!(@new $($id),*);
129            let lock!(@nest $($id),*) = __join_binding.$action();
130
131            ($($id),*)
132        }
133    };
134    (@nest $head:ident, $($id:ident),+) => {
135        ($head, lock!(@nest $($id),*))
136    };
137    (@nest $head:ident) => {
138        $head
139    };
140    (@new $head:ident, $($id:ident),+) => {
141        {
142            use std::borrow::Borrow;
143
144            MutexJoin::new($head.borrow(), lock!(@new $($id),*))
145        }
146    };
147    (@new $head:ident) => {
148        {
149            use std::borrow::Borrow;
150
151            $head.borrow()
152        }
153    };
154    (@brw ref $e:expr) => {
155        &$e
156    };
157    (@brw mut $e:expr) => {
158        &mut $e
159    };
160}
161
162
163#[cfg(never)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn test_join_macro() {
169        let mut group = LockGroup::new();
170
171        let a = group.mutex(18);
172        let b = group.mutex(false);
173        let c = group.mutex("Hello world".to_owned());
174
175        let (a, b, c) = lock!(ref a, ref b, ref c);
176
177        assert_eq!(*a, 18);
178        assert_eq!(*b, false);
179    }
180
181    #[test]
182    fn test_deadlock() {
183        let mut group = LockGroup::new();
184
185        let a = group.mutex(18);
186        let b = group.mutex(false);
187        let c = group.mutex("Hello world".to_owned());
188
189        let (a, b, c) = lock!(ref a, ref b, ref c);
190
191        assert_eq!(*a, 18);
192        assert_eq!(*b, false);
193    }
194
195    #[test]
196    fn test_foo() {
197        fn foo(b: &mut i32, a: &bool) {
198            *b = 5;
199
200            println!("{} {}", b, a);
201        }
202
203        fn foo_locking(b: &Mutex<i32>, a: &Mutex<bool>) {
204            let (mut b, a) = lock!(mut b, ref a);
205            foo(&mut b, &a);
206        }
207
208        let mut group = LockGroup::new();
209
210        let a = group.mutex(false);
211        let b = group.mutex(18);
212
213        foo_locking(&b, &a);
214    }
215}
216*/