mea/mutex/mod.rs
1// Copyright 2024 tison <wander4096@gmail.com>
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! An async mutex for protecting shared data.
16//!
17//! Unlike a standard mutex, this implementation is designed to work with async/await,
18//! ensuring tasks yield properly when the lock is contended. This makes it suitable
19//! for protecting shared resources in async code.
20//!
21//! This mutex will block tasks waiting for the lock to become available. The
22//! mutex can be created via [`new`] and the protected data can be accessed
23//! via the async [`lock`] method.
24//!
25//! # Examples
26//!
27//! ```
28//! # #[tokio::main]
29//! # async fn main() {
30//! use std::sync::Arc;
31//!
32//! use mea::mutex::Mutex;
33//!
34//! let mutex = Arc::new(Mutex::new(0));
35//! let mut handles = Vec::new();
36//!
37//! for i in 0..3 {
38//! let mutex = mutex.clone();
39//! handles.push(tokio::spawn(async move {
40//! let mut lock = mutex.lock().await;
41//! *lock += i;
42//! }));
43//! }
44//!
45//! for handle in handles {
46//! handle.await.unwrap();
47//! }
48//!
49//! let final_value = mutex.lock().await;
50//! assert_eq!(*final_value, 3); // 0 + 1 + 2
51//!
52//! # }
53//! ```
54//!
55//! [`new`]: Mutex::new
56//! [`lock`]: Mutex::lock
57
58use std::cell::UnsafeCell;
59use std::fmt;
60use std::marker::PhantomData;
61use std::mem::ManuallyDrop;
62use std::ops::Deref;
63use std::ops::DerefMut;
64use std::ptr::NonNull;
65use std::sync::Arc;
66
67use crate::internal;
68
69#[cfg(test)]
70mod test;
71
72/// An async mutex for protecting shared data.
73///
74/// See the [module level documentation](self) for more.
75pub struct Mutex<T: ?Sized> {
76 /// Semaphore used to control access to protected data, ensuring mutual exclusion
77 s: internal::Semaphore,
78 /// Container storing the protected data, allowing interior mutability
79 c: UnsafeCell<T>,
80}
81
82unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
83unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
84
85impl<T> From<T> for Mutex<T> {
86 fn from(t: T) -> Self {
87 Self::new(t)
88 }
89}
90
91impl<T: Default> Default for Mutex<T> {
92 fn default() -> Self {
93 Self::new(T::default())
94 }
95}
96
97impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 let mut d = f.debug_struct("Mutex");
100 match self.try_lock() {
101 Some(inner) => d.field("data", &&*inner),
102 None => d.field("data", &format_args!("<locked>")),
103 };
104 d.finish()
105 }
106}
107
108impl<T> Mutex<T> {
109 /// Creates a new mutex in an unlocked state ready for use.
110 ///
111 /// # Examples
112 ///
113 /// ```
114 /// use mea::mutex::Mutex;
115 ///
116 /// let mutex = Mutex::new(5);
117 /// ```
118 pub const fn new(t: T) -> Self {
119 let s = internal::Semaphore::new(1);
120 let c = UnsafeCell::new(t);
121 Self { s, c }
122 }
123
124 /// Consumes the mutex, returning the underlying data.
125 ///
126 /// # Examples
127 ///
128 /// ```
129 /// use mea::mutex::Mutex;
130 ///
131 /// let mutex = Mutex::new(1);
132 /// let n = mutex.into_inner();
133 /// assert_eq!(n, 1);
134 /// ```
135 pub fn into_inner(self) -> T {
136 self.c.into_inner()
137 }
138}
139
140impl<T: ?Sized> Mutex<T> {
141 /// Locks this mutex, causing the current task to yield until the lock has been acquired. When
142 /// the lock has been acquired, function returns a [`MutexGuard`].
143 ///
144 /// This method is async and will yield the current task if the mutex is currently held by
145 /// another task. When the mutex becomes available, the task will be woken up and given the
146 /// lock.
147 ///
148 /// # Cancel safety
149 ///
150 /// This method uses a queue to fairly distribute locks in the order they were requested.
151 /// Cancelling a call to `lock` makes you lose your place in the queue.
152 ///
153 /// # Examples
154 ///
155 /// ```
156 /// # #[tokio::main]
157 /// # async fn main() {
158 /// use mea::mutex::Mutex;
159 ///
160 /// let mutex = Mutex::new(1);
161 ///
162 /// let mut n = mutex.lock().await;
163 /// *n = 2;
164 /// # }
165 /// ```
166 pub async fn lock(&self) -> MutexGuard<'_, T> {
167 self.s.acquire(1).await;
168 MutexGuard { lock: self }
169 }
170
171 /// Attempts to acquire the lock, and returns `None` if the lock is currently held somewhere
172 /// else.
173 ///
174 /// # Examples
175 ///
176 /// ```
177 /// use mea::mutex::Mutex;
178 ///
179 /// let mutex = Mutex::new(1);
180 /// let mut guard = mutex.try_lock().expect("mutex is locked");
181 /// *guard += 1;
182 /// assert_eq!(2, *guard);
183 /// ```
184 pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
185 if self.s.try_acquire(1) {
186 let guard = MutexGuard { lock: self };
187 Some(guard)
188 } else {
189 None
190 }
191 }
192
193 /// Locks this mutex, causing the current task to yield until the lock has been acquired. When
194 /// the lock has been acquired, this returns an [`OwnedMutexGuard`].
195 ///
196 /// This method is async and will yield the current task if the mutex is currently held by
197 /// another task. When the mutex becomes available, the task will be woken up and given the
198 /// lock.
199 ///
200 /// This method is identical to [`Mutex::lock`], except that the returned guard references the
201 /// `Mutex` with an [`Arc`] rather than by borrowing it. Therefore, the `Mutex` must be
202 /// wrapped in an `Arc` to call this method, and the guard will live for the `'static` lifetime,
203 /// as it keeps the `Mutex` alive by holding an `Arc`.
204 ///
205 /// # Cancel safety
206 ///
207 /// This method uses a queue to fairly distribute locks in the order they were requested.
208 /// Cancelling a call to `lock_owned` makes you lose your place in the queue.
209 ///
210 /// # Examples
211 ///
212 /// ```
213 /// # #[tokio::main]
214 /// # async fn main() {
215 /// use std::sync::Arc;
216 ///
217 /// use mea::mutex::Mutex;
218 ///
219 /// let mutex = Arc::new(Mutex::new(1));
220 ///
221 /// let mut n = mutex.clone().lock_owned().await;
222 /// *n = 2;
223 /// # }
224 /// ```
225 pub async fn lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T> {
226 self.s.acquire(1).await;
227 OwnedMutexGuard { lock: self }
228 }
229
230 /// Attempts to acquire the lock, and returns `None` if the lock is currently held somewhere
231 /// else.
232 ///
233 /// This method is identical to [`Mutex::try_lock`], except that the returned guard references
234 /// the `Mutex` with an [`Arc`] rather than by borrowing it. Therefore, the `Mutex` must be
235 /// wrapped in an `Arc` to call this method, and the guard will live for the `'static` lifetime,
236 /// as it keeps the `Mutex` alive by holding an `Arc`.
237 ///
238 /// # Examples
239 ///
240 /// ```
241 /// use std::sync::Arc;
242 ///
243 /// use mea::mutex::Mutex;
244 ///
245 /// let mutex = Arc::new(Mutex::new(1));
246 /// let mut guard = mutex.clone().try_lock_owned().expect("mutex is locked");
247 /// *guard += 1;
248 /// assert_eq!(2, *guard);
249 /// ```
250 pub fn try_lock_owned(self: Arc<Self>) -> Option<OwnedMutexGuard<T>> {
251 if self.s.try_acquire(1) {
252 let guard = OwnedMutexGuard { lock: self };
253 Some(guard)
254 } else {
255 None
256 }
257 }
258
259 /// Returns a mutable reference to the underlying data.
260 ///
261 /// Since this call borrows the `Mutex` mutably, no actual locking needs to take place: the
262 /// mutable borrow statically guarantees no locks exist.
263 ///
264 /// # Examples
265 ///
266 /// ```
267 /// use mea::mutex::Mutex;
268 ///
269 /// let mut mutex = Mutex::new(1);
270 /// let n = mutex.get_mut();
271 /// *n = 2;
272 /// ```
273 pub fn get_mut(&mut self) -> &mut T {
274 self.c.get_mut()
275 }
276}
277
278/// RAII structure used to release the exclusive lock on a mutex when dropped.
279///
280/// This structure is created by the [`lock`] and [`try_lock`] methods on [`Mutex`].
281///
282/// [`lock`]: Mutex::lock
283/// [`try_lock`]: Mutex::try_lock
284///
285/// See the [module level documentation](self) for more.
286#[must_use = "if unused the Mutex will immediately unlock"]
287pub struct MutexGuard<'a, T: ?Sized> {
288 lock: &'a Mutex<T>,
289}
290
291pub(crate) fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a Mutex<T> {
292 guard.lock
293}
294
295unsafe impl<T: ?Sized + Send + Sync> Sync for MutexGuard<'_, T> {}
296
297impl<T: ?Sized> Drop for MutexGuard<'_, T> {
298 fn drop(&mut self) {
299 self.lock.s.release(1);
300 }
301}
302
303impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 fmt::Debug::fmt(&**self, f)
306 }
307}
308
309impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 fmt::Display::fmt(&**self, f)
312 }
313}
314
315impl<T: ?Sized> Deref for MutexGuard<'_, T> {
316 type Target = T;
317 fn deref(&self) -> &Self::Target {
318 unsafe { &*self.lock.c.get() }
319 }
320}
321
322impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
323 fn deref_mut(&mut self) -> &mut Self::Target {
324 unsafe { &mut *self.lock.c.get() }
325 }
326}
327
328impl<'a, T: ?Sized> MutexGuard<'a, T> {
329 /// Makes a new [`MappedMutexGuard`] for a component of the locked data.
330 ///
331 /// This operation cannot fail as the `MutexGuard` passed in already locked the mutex.
332 ///
333 /// This is an associated function that needs to be used as `MutexGuard::map(...)`. A method
334 /// would interfere with methods of the same name on the contents of the locked data.
335 ///
336 /// # Examples
337 ///
338 /// ```
339 /// # #[tokio::main]
340 /// # async fn main() {
341 /// use mea::mutex::Mutex;
342 /// use mea::mutex::MutexGuard;
343 ///
344 /// #[derive(Debug)]
345 /// struct User {
346 /// id: u32,
347 /// profile: UserProfile,
348 /// }
349 ///
350 /// #[derive(Debug)]
351 /// struct UserProfile {
352 /// email: String,
353 /// name: String,
354 /// }
355 ///
356 /// let user = User {
357 /// id: 1,
358 /// profile: UserProfile {
359 /// email: "user@example.com".to_owned(),
360 /// name: "Alice".to_owned(),
361 /// },
362 /// };
363 ///
364 /// let mutex = Mutex::new(user);
365 /// let guard = mutex.lock().await;
366 ///
367 /// // Map to only access the user's profile, allowing fine-grained locking
368 /// let profile_guard = MutexGuard::map(guard, |user| &mut user.profile);
369 /// assert_eq!(profile_guard.email, "user@example.com");
370 /// # }
371 /// ```
372 pub fn map<U, F>(mut orig: Self, f: F) -> MappedMutexGuard<'a, U>
373 where
374 F: FnOnce(&mut T) -> &mut U,
375 U: ?Sized,
376 {
377 let d = NonNull::from(f(&mut *orig));
378 let orig = ManuallyDrop::new(orig);
379 MappedMutexGuard {
380 d,
381 s: &orig.lock.s,
382 variance: PhantomData,
383 }
384 }
385
386 /// Attempts to make a new [`MappedMutexGuard`] for a component of the locked data. The
387 /// original guard is returned if the closure returns `None`.
388 ///
389 /// This operation cannot fail as the `MutexGuard` passed in already locked the mutex.
390 ///
391 /// This is an associated function that needs to be used as `MutexGuard::filter_map(...)`.
392 ///
393 /// A method would interfere with methods of the same name on the contents of the locked data.
394 ///
395 /// # Examples
396 ///
397 /// ```
398 /// # #[tokio::main]
399 /// # async fn main() {
400 /// use mea::mutex::Mutex;
401 /// use mea::mutex::MutexGuard;
402 ///
403 /// #[derive(Debug)]
404 /// struct Database {
405 /// users: std::collections::HashMap<u32, String>,
406 /// admin_user_id: Option<u32>,
407 /// }
408 ///
409 /// let mut db = Database {
410 /// users: std::collections::HashMap::new(),
411 /// admin_user_id: Some(1),
412 /// };
413 /// db.users.insert(1, "admin@example.com".to_owned());
414 ///
415 /// let mutex = Mutex::new(db);
416 /// let guard = mutex.lock().await;
417 ///
418 /// // Try to map to admin user's email if admin exists
419 /// let admin_email_guard = MutexGuard::filter_map(guard, |db| {
420 /// if let Some(admin_id) = db.admin_user_id {
421 /// db.users.get_mut(&admin_id)
422 /// } else {
423 /// None
424 /// }
425 /// })
426 /// .expect("admin user should exist");
427 ///
428 /// assert_eq!(&*admin_email_guard, "admin@example.com");
429 /// # }
430 /// ```
431 pub fn filter_map<U, F>(mut orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
432 where
433 F: FnOnce(&mut T) -> Option<&mut U>,
434 U: ?Sized,
435 {
436 match f(&mut *orig) {
437 Some(d) => {
438 let d = NonNull::from(d);
439 let orig = ManuallyDrop::new(orig);
440 Ok(MappedMutexGuard {
441 d,
442 s: &orig.lock.s,
443 variance: PhantomData,
444 })
445 }
446 None => Err(orig),
447 }
448 }
449}
450
451/// An owned handle to a held `Mutex`.
452///
453/// This guard is only available from a [`Mutex`] that is wrapped in an [`Arc`]. It is identical to
454/// [`MutexGuard`], except that rather than borrowing the `Mutex`, it clones the `Arc`, incrementing
455/// the reference count. This means that unlike `MutexGuard`, it will have the `'static` lifetime.
456///
457/// As long as you have this guard, you have exclusive access to the underlying `T`. The guard
458/// internally keeps a reference-counted pointer to the original `Mutex`, so even if the lock goes
459/// away, the guard remains valid.
460///
461/// The lock is automatically released whenever the guard is dropped, at which point `lock` will
462/// succeed yet again.
463///
464/// See the [module level documentation](self) for more.
465#[must_use = "if unused the Mutex will immediately unlock"]
466pub struct OwnedMutexGuard<T: ?Sized> {
467 lock: Arc<Mutex<T>>,
468}
469
470pub(crate) fn owned_guard_lock<T: ?Sized>(guard: &OwnedMutexGuard<T>) -> Arc<Mutex<T>> {
471 guard.lock.clone()
472}
473
474unsafe impl<T: ?Sized + Send + Sync> Sync for OwnedMutexGuard<T> {}
475
476impl<T: ?Sized> Drop for OwnedMutexGuard<T> {
477 fn drop(&mut self) {
478 self.lock.s.release(1);
479 }
480}
481
482impl<T: ?Sized + fmt::Debug> fmt::Debug for OwnedMutexGuard<T> {
483 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484 fmt::Debug::fmt(&**self, f)
485 }
486}
487
488impl<T: ?Sized + fmt::Display> fmt::Display for OwnedMutexGuard<T> {
489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490 fmt::Display::fmt(&**self, f)
491 }
492}
493
494impl<T: ?Sized> Deref for OwnedMutexGuard<T> {
495 type Target = T;
496 fn deref(&self) -> &Self::Target {
497 unsafe { &*self.lock.c.get() }
498 }
499}
500
501impl<T: ?Sized> DerefMut for OwnedMutexGuard<T> {
502 fn deref_mut(&mut self) -> &mut Self::Target {
503 unsafe { &mut *self.lock.c.get() }
504 }
505}
506
507impl<T: ?Sized> OwnedMutexGuard<T> {
508 /// Makes a new [`OwnedMappedMutexGuard`] for a component of the locked data.
509 ///
510 /// This operation cannot fail as the `OwnedMutexGuard` passed in already locked the mutex.
511 ///
512 /// This is an associated function that needs to be used as `OwnedMutexGuard::map(...)`. A
513 /// method would interfere with methods of the same name on the contents of the locked data.
514 ///
515 /// # Examples
516 ///
517 /// ```
518 /// # #[tokio::main]
519 /// # async fn main() {
520 /// use std::sync::Arc;
521 ///
522 /// use mea::mutex::Mutex;
523 /// use mea::mutex::OwnedMutexGuard;
524 ///
525 /// struct Config {
526 /// name: String,
527 /// value: u32,
528 /// }
529 ///
530 /// let config = Config {
531 /// name: "front size".to_owned(),
532 /// value: 42,
533 /// };
534 ///
535 /// let mutex = Arc::new(Mutex::new(config));
536 /// let guard = mutex.clone().lock_owned().await;
537 ///
538 /// // Map to access only the value field
539 /// let value_guard = OwnedMutexGuard::map(guard, |config| &mut config.value);
540 /// assert_eq!(*value_guard, 42);
541 /// # }
542 /// ```
543 pub fn map<U, F>(mut orig: Self, f: F) -> OwnedMappedMutexGuard<T, U>
544 where
545 F: FnOnce(&mut T) -> &mut U,
546 U: ?Sized,
547 {
548 let d = NonNull::from(f(&mut *orig));
549
550 let guard = ManuallyDrop::new(orig);
551
552 let lock = unsafe { std::ptr::read(&guard.lock) };
553
554 OwnedMappedMutexGuard {
555 lock,
556 d,
557 variance: PhantomData,
558 }
559 }
560
561 /// Attempts to make a new [`OwnedMappedMutexGuard`] for a component of the locked data. The
562 /// original guard is returned if the closure returns `None`.
563 ///
564 /// This operation cannot fail as the `OwnedMutexGuard` passed in already locked the mutex.
565 ///
566 /// This is an associated function that needs to be used as `OwnedMutexGuard::filter_map(...)`.
567 ///
568 /// A method would interfere with methods of the same name on the contents of the locked data.
569 ///
570 /// # Examples
571 ///
572 /// ```
573 /// # #[tokio::main]
574 /// # async fn main() {
575 /// use std::sync::Arc;
576 ///
577 /// use mea::mutex::Mutex;
578 /// use mea::mutex::OwnedMutexGuard;
579 ///
580 /// let data = vec![1, 2, 3, 4, 5];
581 /// let mutex = Arc::new(Mutex::new(data));
582 /// let guard = mutex.clone().lock_owned().await;
583 ///
584 /// // Map to the first element
585 /// let first_guard =
586 /// OwnedMutexGuard::filter_map(guard, |vec| vec.get_mut(0)).expect("vec should not be empty");
587 ///
588 /// assert_eq!(*first_guard, 1);
589 /// # }
590 /// ```
591 pub fn filter_map<U, F>(mut orig: Self, f: F) -> Result<OwnedMappedMutexGuard<T, U>, Self>
592 where
593 F: FnOnce(&mut T) -> Option<&mut U>,
594 U: ?Sized,
595 {
596 match f(&mut *orig) {
597 Some(d) => {
598 let d = NonNull::from(d);
599 let guard = ManuallyDrop::new(orig);
600
601 // SAFETY: We safely extract the Arc from the ManuallyDrop guard
602 let lock = unsafe { std::ptr::read(&guard.lock) };
603
604 Ok(OwnedMappedMutexGuard {
605 lock,
606 d,
607 variance: PhantomData,
608 })
609 }
610 None => Err(orig),
611 }
612 }
613}
614
615/// RAII structure used to release the exclusive lock on a mutex when dropped, for a mapped
616/// component of the locked data.
617///
618/// This structure is created by the [`map`] and [`filter_map`] methods on [`MutexGuard`]. It allows
619/// you to hold a lock on a subfield of the protected data, enabling more fine-grained access
620/// control while maintaining the same locking semantics.
621///
622/// As long as you have this guard, you have exclusive access to the underlying `T`. The guard
623/// internally keeps a reference to the original mutex's semaphore, so the original lock is
624/// maintained until this guard is dropped.
625///
626/// `MappedMutexGuard` implements [`Send`] and [`Sync`]
627/// when the underlying data type supports these traits, allowing it to be used across task
628/// boundaries and shared between threads safely.
629///
630/// See the [module level documentation](self) for more.
631///
632/// [`map`]: MutexGuard::map
633/// [`filter_map`]: MutexGuard::filter_map
634///
635/// # Examples
636///
637/// ```
638/// # #[tokio::main]
639/// # async fn main() {
640/// use mea::mutex::Mutex;
641/// use mea::mutex::MutexGuard;
642///
643/// #[derive(Debug)]
644/// struct User {
645/// id: u32,
646/// profile: UserProfile,
647/// }
648///
649/// #[derive(Debug)]
650/// struct UserProfile {
651/// email: String,
652/// name: String,
653/// }
654///
655/// let user = User {
656/// id: 1,
657/// profile: UserProfile {
658/// email: "user@example.com".to_owned(),
659/// name: "Alice".to_owned(),
660/// },
661/// };
662///
663/// let mutex = Mutex::new(user);
664/// let guard = mutex.lock().await;
665/// let profile_guard = MutexGuard::map(guard, |user| &mut user.profile);
666///
667/// // Now we can only access the user's profile
668/// assert_eq!(profile_guard.email, "user@example.com");
669/// # }
670/// ```
671#[must_use = "if unused the Mutex will immediately unlock"]
672pub struct MappedMutexGuard<'a, T: ?Sized> {
673 /// Non-null pointer to the mapped data
674 d: NonNull<T>,
675 /// Reference to the original mutex's semaphore, used for releasing the lock
676 s: &'a internal::Semaphore,
677 variance: PhantomData<&'a mut T>,
678}
679
680// SAFETY: MappedMutexGuard can be safely sent between threads when T: Send.
681// The guard holds exclusive access to the data protected by the mutex lock,
682// and the NonNull<T> pointer remains valid for the guard's lifetime.
683// This is essential for async tasks that may be moved between threads at .await points.
684unsafe impl<T: ?Sized + Send> Send for MappedMutexGuard<'_, T> {}
685
686// SAFETY: MappedMutexGuard can be safely shared between threads (Sync) when T: Sync.
687// Through &MappedMutexGuard, you can only get &T, so if T itself allows sharing references
688// across threads, then sharing MappedMutexGuard references is also safe.
689unsafe impl<T: ?Sized + Sync> Sync for MappedMutexGuard<'_, T> {}
690
691impl<T: ?Sized> Drop for MappedMutexGuard<'_, T> {
692 fn drop(&mut self) {
693 self.s.release(1);
694 }
695}
696
697impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedMutexGuard<'_, T> {
698 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
699 fmt::Debug::fmt(&**self, f)
700 }
701}
702
703impl<T: ?Sized + fmt::Display> fmt::Display for MappedMutexGuard<'_, T> {
704 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705 fmt::Display::fmt(&**self, f)
706 }
707}
708
709impl<T: ?Sized> Deref for MappedMutexGuard<'_, T> {
710 type Target = T;
711 fn deref(&self) -> &Self::Target {
712 // SAFETY: we hold the lock and the NonNull pointer is valid for the guard's lifetime
713 unsafe { self.d.as_ref() }
714 }
715}
716
717impl<T: ?Sized> DerefMut for MappedMutexGuard<'_, T> {
718 fn deref_mut(&mut self) -> &mut Self::Target {
719 // SAFETY: we hold the lock and the NonNull pointer is valid for the guard's lifetime
720 unsafe { self.d.as_mut() }
721 }
722}
723
724impl<'a, T: ?Sized> MappedMutexGuard<'a, T> {
725 /// Makes a new [`MappedMutexGuard`] for a component of the locked data.
726 ///
727 /// This operation cannot fail as the `MappedMutexGuard` passed in already locked the mutex.
728 ///
729 /// This is an associated function that needs to be used as `MappedMutexGuard::map(...)`. A
730 /// method would interfere with methods of the same name on the contents of the locked data.
731 ///
732 /// # Examples
733 ///
734 /// ```
735 /// # #[tokio::main]
736 /// # async fn main() {
737 /// use mea::mutex::MappedMutexGuard;
738 /// use mea::mutex::Mutex;
739 /// use mea::mutex::MutexGuard;
740 ///
741 /// #[derive(Debug)]
742 /// struct User {
743 /// id: u32,
744 /// profile: UserProfile,
745 /// }
746 ///
747 /// #[derive(Debug)]
748 /// struct UserProfile {
749 /// email: String,
750 /// name: String,
751 /// }
752 ///
753 /// let user = User {
754 /// id: 1,
755 /// profile: UserProfile {
756 /// email: "user@example.com".to_owned(),
757 /// name: "Alice".to_owned(),
758 /// },
759 /// };
760 ///
761 /// let mutex = Mutex::new(user);
762 /// let guard = mutex.lock().await;
763 ///
764 /// // First map to user profile
765 /// let profile_guard = MutexGuard::map(guard, |user| &mut user.profile);
766 /// // Then map to the email field specifically
767 /// let email_guard = MappedMutexGuard::map(profile_guard, |profile| &mut profile.email);
768 ///
769 /// assert_eq!(&*email_guard, "user@example.com");
770 /// # }
771 /// ```
772 pub fn map<U, F>(mut orig: Self, f: F) -> MappedMutexGuard<'a, U>
773 where
774 F: FnOnce(&mut T) -> &mut U,
775 U: ?Sized,
776 {
777 // Use DerefMut to safely get mutable reference, avoiding explicit unsafe block
778 let d = NonNull::from(f(&mut *orig));
779 let orig = ManuallyDrop::new(orig);
780 MappedMutexGuard {
781 d,
782 s: orig.s,
783 variance: PhantomData,
784 }
785 }
786
787 /// Attempts to make a new [`MappedMutexGuard`] for a component of the locked data. The
788 /// original guard is returned if the closure returns `None`.
789 ///
790 /// This operation cannot fail as the `MappedMutexGuard` passed in already locked the mutex.
791 ///
792 /// This is an associated function that needs to be used as `MappedMutexGuard::filter_map(...)`.
793 /// A method would interfere with methods of the same name on the contents of the locked
794 /// data.
795 ///
796 /// # Examples
797 ///
798 /// ```
799 /// # #[tokio::main]
800 /// # async fn main() {
801 /// use mea::mutex::MappedMutexGuard;
802 /// use mea::mutex::Mutex;
803 /// use mea::mutex::MutexGuard;
804 ///
805 /// #[derive(Debug)]
806 /// struct Data {
807 /// id: u32,
808 /// value: Option<String>,
809 /// }
810 ///
811 /// let data = Data {
812 /// id: 1,
813 /// value: Some("hello".to_owned()),
814 /// };
815 ///
816 /// let mutex = Mutex::new(data);
817 /// let guard = mutex.lock().await;
818 ///
819 /// // First map to the value field
820 /// let value_guard = MutexGuard::map(guard, |data| &mut data.value);
821 /// // Then try to map to the inner string if it exists
822 /// let string_guard =
823 /// MappedMutexGuard::filter_map(value_guard, |opt| opt.as_mut()).expect("value should exist");
824 ///
825 /// assert_eq!(&*string_guard, "hello");
826 /// # }
827 /// ```
828 pub fn filter_map<U, F>(mut orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
829 where
830 F: FnOnce(&mut T) -> Option<&mut U>,
831 U: ?Sized,
832 {
833 // Use DerefMut to safely get mutable reference, avoiding explicit unsafe block
834 match f(&mut *orig) {
835 Some(d) => {
836 let d = NonNull::from(d);
837 let orig = ManuallyDrop::new(orig);
838 Ok(MappedMutexGuard {
839 d,
840 s: orig.s,
841 variance: PhantomData,
842 })
843 }
844 None => Err(orig),
845 }
846 }
847}
848
849/// An owned handle to a held `Mutex` for a mapped component of the locked data.
850///
851/// This guard is only available from a [`Mutex`] that is wrapped in an [`Arc`]. It is similar to
852/// [`MappedMutexGuard`], except that rather than borrowing the `Mutex`, it clones the `Arc`,
853/// incrementing the reference count. This means that unlike `MappedMutexGuard`, it will have
854/// the `'static` lifetime.
855///
856/// This structure is created by the [`map`] and [`filter_map`] methods on [`OwnedMutexGuard`].
857/// It allows you to hold a lock on a subfield of the protected data, enabling more fine-grained
858/// access control while maintaining the same locking semantics.
859///
860/// As long as you have this guard, you have exclusive access to the underlying `U`. The guard
861/// internally keeps a reference-counted pointer to the original `Mutex`, so even if the lock goes
862/// away, the guard remains valid.
863///
864/// The lock is automatically released whenever the guard is dropped, at which point `lock` will
865/// succeed yet again.
866///
867/// See the [module level documentation](self) for more.
868///
869/// [`map`]: OwnedMutexGuard::map
870/// [`filter_map`]: OwnedMutexGuard::filter_map
871///
872/// # Examples
873///
874/// ```
875/// # #[tokio::main]
876/// # async fn main() {
877/// use std::sync::Arc;
878///
879/// use mea::mutex::Mutex;
880/// use mea::mutex::OwnedMutexGuard;
881///
882/// struct Data {
883/// value: u32,
884/// }
885///
886/// let data = Data { value: 42 };
887/// let mutex = Arc::new(Mutex::new(data));
888/// let guard = mutex.clone().lock_owned().await;
889/// let value_guard = OwnedMutexGuard::map(guard, |data| &mut data.value);
890///
891/// assert_eq!(*value_guard, 42);
892/// # }
893/// ```
894#[must_use = "if unused the Mutex will immediately unlock"]
895pub struct OwnedMappedMutexGuard<T: ?Sized, U: ?Sized> {
896 // This Arc acts as an ownership certificate, ensuring the Mutex remains valid
897 // and the lock is not released
898 lock: Arc<Mutex<T>>,
899 // This NonNull pointer precisely points to the subfield U, telling us which
900 // memory location we can operate on, with compile-time guarantee of non-null
901 d: NonNull<U>,
902 variance: PhantomData<U>,
903}
904
905// SAFETY: OwnedMappedMutexGuard can be safely sent between threads when T: Send and U: Send.
906// It holds exclusive access to the data protected by the mutex lock, and the raw pointer
907// remains valid for the guard's lifetime. This is essential for async tasks that may be
908// moved between threads at .await points.
909unsafe impl<T: ?Sized + Send, U: ?Sized + Send> Send for OwnedMappedMutexGuard<T, U> {}
910
911// SAFETY: OwnedMappedMutexGuard can be safely shared between threads (Sync) when T: Send + Sync and
912// U: Send + Sync. Through &OwnedMappedMutexGuard, you can only get &U, so if U itself allows
913// sharing references across threads, then sharing OwnedMappedMutexGuard references is also safe.
914// We require T: Send + Sync for maximum safety and ecosystem compatibility.
915unsafe impl<T: ?Sized + Send + Sync, U: ?Sized + Send + Sync> Sync for OwnedMappedMutexGuard<T, U> {}
916
917impl<T: ?Sized, U: ?Sized> Drop for OwnedMappedMutexGuard<T, U> {
918 fn drop(&mut self) {
919 // Release the lock by calling release on the semaphore
920 self.lock.s.release(1);
921 }
922}
923
924impl<T: ?Sized, U: ?Sized + fmt::Debug> fmt::Debug for OwnedMappedMutexGuard<T, U> {
925 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
926 fmt::Debug::fmt(&**self, f)
927 }
928}
929
930impl<T: ?Sized, U: ?Sized + fmt::Display> fmt::Display for OwnedMappedMutexGuard<T, U> {
931 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
932 fmt::Display::fmt(&**self, f)
933 }
934}
935
936impl<T: ?Sized, U: ?Sized> Deref for OwnedMappedMutexGuard<T, U> {
937 type Target = U;
938 fn deref(&self) -> &Self::Target {
939 // SAFETY: we hold the lock and the NonNull pointer is valid for the guard's lifetime
940 // The Arc ensures the underlying data remains valid
941 unsafe { self.d.as_ref() }
942 }
943}
944
945impl<T: ?Sized, U: ?Sized> DerefMut for OwnedMappedMutexGuard<T, U> {
946 fn deref_mut(&mut self) -> &mut Self::Target {
947 // SAFETY: we hold the lock and the NonNull pointer is valid for the guard's lifetime
948 // The Arc ensures the underlying data remains valid
949 unsafe { self.d.as_mut() }
950 }
951}
952
953impl<T: ?Sized, U: ?Sized> OwnedMappedMutexGuard<T, U> {
954 /// Makes a new [`OwnedMappedMutexGuard`] for a component of the locked data.
955 ///
956 /// This operation cannot fail as the `OwnedMappedMutexGuard` passed in already locked the
957 /// mutex.
958 ///
959 /// This is an associated function that needs to be used as `OwnedMappedMutexGuard::map(...)`. A
960 /// method would interfere with methods of the same name on the contents of the locked data.
961 ///
962 /// # Examples
963 ///
964 /// ```
965 /// # #[tokio::main]
966 /// # async fn main() {
967 /// use std::sync::Arc;
968 ///
969 /// use mea::mutex::Mutex;
970 /// use mea::mutex::OwnedMappedMutexGuard;
971 /// use mea::mutex::OwnedMutexGuard;
972 ///
973 /// #[derive(Debug)]
974 /// struct Config {
975 /// host: String,
976 /// port: u16,
977 /// }
978 ///
979 /// let config = Config {
980 /// host: "localhost".to_owned(),
981 /// port: 8080,
982 /// };
983 ///
984 /// let mutex = Arc::new(Mutex::new(config));
985 /// let guard = mutex.clone().lock_owned().await;
986 ///
987 /// // First map to config
988 /// let config_guard = OwnedMutexGuard::map(guard, |config| &mut config.host);
989 /// // Then map to the host string specifically
990 /// let host_guard = OwnedMappedMutexGuard::map(config_guard, |host| host.as_mut_str());
991 ///
992 /// assert_eq!(&*host_guard, "localhost");
993 /// # }
994 /// ```
995 pub fn map<V, F>(mut orig: Self, f: F) -> OwnedMappedMutexGuard<T, V>
996 where
997 F: FnOnce(&mut U) -> &mut V,
998 V: ?Sized,
999 {
1000 // Use DerefMut to maintain consistency with other map implementations
1001 let d = NonNull::from(f(&mut *orig));
1002 let orig = ManuallyDrop::new(orig);
1003
1004 // SAFETY: We safely extract the Arc from the ManuallyDrop guard
1005 let lock = unsafe { std::ptr::read(&orig.lock) };
1006
1007 OwnedMappedMutexGuard {
1008 lock,
1009 d,
1010 variance: PhantomData,
1011 }
1012 }
1013
1014 /// Attempts to make a new [`OwnedMappedMutexGuard`] for a component of the locked data. The
1015 /// original guard is returned if the closure returns `None`.
1016 ///
1017 /// This operation cannot fail as the `OwnedMappedMutexGuard` passed in already locked the
1018 /// mutex.
1019 ///
1020 /// This is an associated function that needs to be used as
1021 /// `OwnedMappedMutexGuard::filter_map(...)`. A method would interfere with methods of the same
1022 /// name on the contents of the locked data.
1023 ///
1024 /// # Examples
1025 ///
1026 /// ```
1027 /// # #[tokio::main]
1028 /// # async fn main() {
1029 /// use std::sync::Arc;
1030 ///
1031 /// use mea::mutex::Mutex;
1032 /// use mea::mutex::OwnedMappedMutexGuard;
1033 /// use mea::mutex::OwnedMutexGuard;
1034 ///
1035 /// #[derive(Debug)]
1036 /// struct Node {
1037 /// value: i32,
1038 /// left: Option<Box<Node>>,
1039 /// right: Option<Box<Node>>,
1040 /// }
1041 ///
1042 /// let node = Node {
1043 /// value: 10,
1044 /// left: Some(Box::new(Node {
1045 /// value: 5,
1046 /// left: None,
1047 /// right: None,
1048 /// })),
1049 /// right: None,
1050 /// };
1051 ///
1052 /// let mutex = Arc::new(Mutex::new(node));
1053 /// let guard = mutex.clone().lock_owned().await;
1054 ///
1055 /// // First map to left child
1056 /// let left_guard = OwnedMutexGuard::map(guard, |node| &mut node.left);
1057 /// // Try to access the left child if it exists
1058 /// let child_guard = OwnedMappedMutexGuard::filter_map(left_guard, |left| {
1059 /// left.as_mut().map(|boxed| boxed.as_mut())
1060 /// })
1061 /// .expect("left child should exist");
1062 ///
1063 /// assert_eq!(child_guard.value, 5);
1064 /// # }
1065 /// ```
1066 pub fn filter_map<V, F>(mut orig: Self, f: F) -> Result<OwnedMappedMutexGuard<T, V>, Self>
1067 where
1068 F: FnOnce(&mut U) -> Option<&mut V>,
1069 V: ?Sized,
1070 {
1071 // Use DerefMut to maintain consistency with other filter_map implementations
1072 match f(&mut *orig) {
1073 Some(d) => {
1074 let d = NonNull::from(d);
1075 let orig = ManuallyDrop::new(orig);
1076
1077 // SAFETY: We safely extract the Arc from the ManuallyDrop guard
1078 let lock = unsafe { std::ptr::read(&orig.lock) };
1079
1080 Ok(OwnedMappedMutexGuard {
1081 lock,
1082 d,
1083 variance: PhantomData,
1084 })
1085 }
1086 None => Err(orig),
1087 }
1088 }
1089}