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*/