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