lock_order/
wrap.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Wrappers for using `Locked` features on newtypes.
6
7use crate::{
8    LockBefore, LockFor, Locked, OwnedTupleWrapper, RwLockFor, TupleWrapper, UnlockedAccess,
9};
10use core::ops::Deref;
11
12/// A prelude to include all the wrapper traits into scope and thus wrappers can
13/// be used as if they were raw [`Locked`] instances.
14pub mod prelude {
15    pub use super::{LockedWrapperApi as _, LockedWrapperUnlockedApi as _};
16}
17
18/// A trait implemented by newtypes on [`Locked`]
19pub trait LockedWrapper<T, L>
20where
21    T: Deref,
22{
23    /// The same wrapper at a different lock level.
24    type AtLockLevel<'l, M>: LockedWrapper<&'l T::Target, M>
25    where
26        M: 'l,
27        T: 'l;
28
29    /// The same wrapper with a different locked state.
30    type CastWrapper<X>: LockedWrapper<X, L>
31    where
32        X: Deref,
33        X::Target: Sized;
34
35    /// Wraps [`Locked`] into a newtype.
36    fn wrap<'l, M>(locked: Locked<&'l T::Target, M>) -> Self::AtLockLevel<'l, M>
37    where
38        M: 'l,
39        T: 'l;
40
41    /// Wraps a [`Locked`] into a different wrapper implementation.
42    fn wrap_cast<R: Deref>(locked: Locked<R, L>) -> Self::CastWrapper<R>
43    where
44        R::Target: Sized;
45
46    /// Gets a mutable reference to the wrapped `Locked`.
47    fn get_mut(&mut self) -> &mut Locked<T, L>;
48
49    /// Gets an immutable reference to the wrapped `Locked`.
50    fn get(&self) -> &Locked<T, L>;
51}
52
53impl<T, L> LockedWrapper<T, L> for Locked<T, L>
54where
55    T: Deref,
56    T::Target: Sized,
57{
58    type AtLockLevel<'l, M>
59        = Locked<&'l T::Target, M>
60    where
61        M: 'l,
62        T: 'l;
63
64    type CastWrapper<X>
65        = Locked<X, L>
66    where
67        X: Deref,
68        X::Target: Sized;
69
70    fn wrap<'l, M>(locked: Locked<&'l T::Target, M>) -> Self::AtLockLevel<'l, M>
71    where
72        M: 'l,
73        T: 'l,
74    {
75        locked
76    }
77
78    fn wrap_cast<R: Deref>(locked: Locked<R, L>) -> Self::CastWrapper<R>
79    where
80        R::Target: Sized,
81    {
82        locked
83    }
84
85    fn get_mut(&mut self) -> &mut Locked<T, L> {
86        self
87    }
88
89    fn get(&self) -> &Locked<T, L> {
90        self
91    }
92}
93
94/// Provides an API with the same shape as [`Locked`] for any type implementing
95/// [`LockedWrapper`].
96pub trait LockedWrapperUnlockedApi<'a, T: 'a, L: 'a>: LockedWrapper<&'a T, L> {
97    /// Like [`Locked::unlocked_access`].
98    fn unlocked_access<M>(&self) -> T::Guard<'a>
99    where
100        T: UnlockedAccess<M>,
101    {
102        self.get().unlocked_access::<M>()
103    }
104
105    /// Like [`Locked::unlocked_access_with`].
106    fn unlocked_access_with<M, X>(&self, f: impl FnOnce(&'a T) -> &'a X) -> X::Guard<'a>
107    where
108        X: UnlockedAccess<M>,
109    {
110        self.get().unlocked_access_with::<M, X>(f)
111    }
112}
113
114impl<'a, O, T, L> LockedWrapperUnlockedApi<'a, T, L> for O
115where
116    T: 'a,
117    L: 'a,
118    O: LockedWrapper<&'a T, L>,
119{
120}
121
122/// Provides an API with the same shape as [`Locked`] for any type implementing
123/// [`LockedWrapper`].
124pub trait LockedWrapperApi<T, L>: LockedWrapper<T, L>
125where
126    T: Deref,
127    T::Target: Sized,
128{
129    /// Like [`Locked::lock`].
130    fn lock<'a, M>(&'a mut self) -> <T::Target as LockFor<M>>::Guard<'a>
131    where
132        T: 'a,
133        T::Target: LockFor<M>,
134        L: LockBefore<M> + 'a,
135    {
136        self.get_mut().lock::<M>()
137    }
138
139    /// Like [`Locked::lock_and`].
140    fn lock_and<'a, M>(
141        &'a mut self,
142    ) -> (<T::Target as LockFor<M>>::Guard<'a>, Self::AtLockLevel<'a, M>)
143    where
144        T::Target: LockFor<M>,
145        L: LockBefore<M> + 'a,
146    {
147        let (guard, locked) = self.get_mut().lock_and::<M>();
148        (guard, Self::wrap(locked))
149    }
150
151    /// Like [`Locked::lock_with`].
152    fn lock_with<'a, M, X>(&'a mut self, f: impl FnOnce(&T::Target) -> &X) -> X::Guard<'a>
153    where
154        T: 'a,
155        X: LockFor<M>,
156        L: LockBefore<M> + 'a,
157    {
158        self.get_mut().lock_with::<M, X>(f)
159    }
160
161    /// Like [`Locked::lock_with_and`].
162    fn lock_with_and<'a, M, X>(
163        &'a mut self,
164        f: impl FnOnce(&T::Target) -> &X,
165    ) -> (X::Guard<'a>, Self::AtLockLevel<'a, M>)
166    where
167        X: LockFor<M>,
168        L: LockBefore<M> + 'a,
169    {
170        let (guard, locked) = self.get_mut().lock_with_and::<M, X>(f);
171        (guard, Self::wrap(locked))
172    }
173
174    /// Like [`Locked::read_lock`].
175    fn read_lock<'a, M>(&'a mut self) -> <T::Target as RwLockFor<M>>::ReadGuard<'a>
176    where
177        T: 'a,
178        T::Target: RwLockFor<M>,
179        L: LockBefore<M> + 'a,
180    {
181        self.get_mut().read_lock::<M>()
182    }
183
184    /// Like [`Locked::read_lock_and`].
185    fn read_lock_and<'a, M>(
186        &'a mut self,
187    ) -> (<T::Target as RwLockFor<M>>::ReadGuard<'a>, Self::AtLockLevel<'a, M>)
188    where
189        T::Target: RwLockFor<M>,
190        L: LockBefore<M> + 'a,
191    {
192        let (guard, locked) = self.get_mut().read_lock_and::<M>();
193        (guard, Self::wrap(locked))
194    }
195
196    /// Like [`Locked::read_lock_with`].
197    fn read_lock_with<'a, M, X>(&'a mut self, f: impl FnOnce(&T::Target) -> &X) -> X::ReadGuard<'a>
198    where
199        T: 'a,
200        X: RwLockFor<M>,
201        L: LockBefore<M> + 'a,
202    {
203        self.get_mut().read_lock_with::<M, X>(f)
204    }
205
206    /// Like [`Locked::read_lock_with_and`].
207    fn read_lock_with_and<'a, M, X>(
208        &'a mut self,
209        f: impl FnOnce(&T::Target) -> &X,
210    ) -> (X::ReadGuard<'a>, Self::AtLockLevel<'a, M>)
211    where
212        X: RwLockFor<M>,
213        L: LockBefore<M> + 'a,
214    {
215        let (guard, locked) = self.get_mut().read_lock_with_and::<M, X>(f);
216        (guard, Self::wrap(locked))
217    }
218
219    /// Like [`Locked::write_lock`].
220    fn write_lock<'a, M>(&'a mut self) -> <T::Target as RwLockFor<M>>::WriteGuard<'a>
221    where
222        T: 'a,
223        T::Target: RwLockFor<M>,
224        L: LockBefore<M> + 'a,
225    {
226        self.get_mut().write_lock::<M>()
227    }
228
229    /// Like [`Locked::write_lock_and`].
230    fn write_lock_and<'a, M>(
231        &'a mut self,
232    ) -> (<T::Target as RwLockFor<M>>::WriteGuard<'a>, Self::AtLockLevel<'a, M>)
233    where
234        T::Target: RwLockFor<M>,
235        L: LockBefore<M> + 'a,
236    {
237        let (guard, locked) = self.get_mut().write_lock_and::<M>();
238        (guard, Self::wrap(locked))
239    }
240
241    /// Like [`Locked::write_lock_with`].
242    fn write_lock_with<'a, M, X>(
243        &'a mut self,
244        f: impl FnOnce(&T::Target) -> &X,
245    ) -> X::WriteGuard<'a>
246    where
247        T: 'a,
248        X: RwLockFor<M>,
249        L: LockBefore<M> + 'a,
250    {
251        self.get_mut().write_lock_with::<M, X>(f)
252    }
253
254    /// Like [`Locked::write_lock_with_and`].
255    fn write_lock_with_and<'a, M, X>(
256        &'a mut self,
257        f: impl FnOnce(&T::Target) -> &X,
258    ) -> (X::WriteGuard<'a>, Self::AtLockLevel<'a, M>)
259    where
260        X: RwLockFor<M>,
261        L: LockBefore<M> + 'a,
262    {
263        let (guard, locked) = self.get_mut().write_lock_with_and::<M, X>(f);
264        (guard, Self::wrap(locked))
265    }
266
267    /// Like [`Locked::as_owned`].
268    fn as_owned(&mut self) -> Self::AtLockLevel<'_, L> {
269        Self::wrap(self.get_mut().cast_with(|s| s))
270    }
271
272    /// Like [`Locked::cast`].
273    fn cast<'a, R>(&'a mut self) -> Self::CastWrapper<&'a R>
274    where
275        T: 'a,
276        L: 'a,
277        T::Target: AsRef<R>,
278    {
279        Self::wrap_cast(self.get_mut().cast_with(AsRef::as_ref))
280    }
281
282    /// Like [`Locked::cast_with`]
283    fn cast_with<'a, R>(&'a mut self, f: impl FnOnce(&T::Target) -> &R) -> Self::CastWrapper<&'a R>
284    where
285        T: 'a,
286        L: 'a,
287    {
288        Self::wrap_cast(self.get_mut().cast_with::<R>(f))
289    }
290
291    /// Like [`Locked::cast_locked`].
292    fn cast_locked<'a, M>(&'a mut self) -> Self::AtLockLevel<'a, M>
293    where
294        L: LockBefore<M> + 'a,
295    {
296        Self::wrap(self.get_mut().cast_locked::<M>())
297    }
298
299    /// Like [`Locked::copied`].
300    fn copied(&self) -> T::Target
301    where
302        T::Target: Copy,
303    {
304        self.get().copied()
305    }
306
307    /// Like [`Locked::adopt`].
308    fn adopt<'a, N>(
309        &'a mut self,
310        n: &'a N,
311    ) -> Self::CastWrapper<OwnedTupleWrapper<&'a T::Target, &'a N>>
312    where
313        T: 'a,
314        L: 'a,
315    {
316        Self::wrap_cast(self.get_mut().adopt(n))
317    }
318
319    /// Like [`Locked::cast_left`].
320    fn cast_left<'a, X, A: Deref + 'a, B: Deref + 'a, F: FnOnce(&A::Target) -> &X>(
321        &'a mut self,
322        f: F,
323    ) -> Self::CastWrapper<OwnedTupleWrapper<&'a X, &'a B::Target>>
324    where
325        L: 'a,
326        T: Deref<Target = TupleWrapper<A, B>> + 'a,
327    {
328        Self::wrap_cast(self.get_mut().cast_left(f))
329    }
330
331    /// Like [`Locked::cast_right`].
332    fn cast_right<'a, X, A: Deref + 'a, B: Deref + 'a, F: FnOnce(&B::Target) -> &X>(
333        &'a mut self,
334        f: F,
335    ) -> Self::CastWrapper<OwnedTupleWrapper<&'a A::Target, &'a X>>
336    where
337        L: 'a,
338        T: Deref<Target = TupleWrapper<A, B>> + 'a,
339    {
340        Self::wrap_cast(self.get_mut().cast_right(f))
341    }
342
343    /// Like [`Locked::replace`].
344    fn replace<'a, N>(&'a mut self, n: &'a N) -> Self::CastWrapper<&'a N>
345    where
346        L: 'a,
347        T: 'a,
348    {
349        Self::wrap_cast(self.get_mut().replace(n))
350    }
351}
352
353impl<T, L, O> LockedWrapperApi<T, L> for O
354where
355    T: Deref,
356    T::Target: Sized,
357    O: LockedWrapper<T, L>,
358{
359}
360
361pub mod disable {
362    use core::marker::PhantomData;
363    use core::ops::Deref;
364
365    use super::LockedWrapper;
366    use crate::{
367        LockBefore, LockFor, Locked, OwnedTupleWrapper, RwLockFor, TupleWrapper, Unlocked,
368    };
369
370    /// A prelude to include all the *disabled* wrapper traits into scope and
371    /// thus wrappers can be used as if they were raw [`Locked`] instances.
372    pub mod prelude {
373        pub use super::super::LockedWrapperUnlockedApi as _;
374        pub use super::LockedDisabledWrapperApi as _;
375    }
376
377    /// A trait enabling [`LockedDisabledWrapperApi`].
378    ///
379    /// # Safety
380    ///
381    /// This is marked as unsafe to steer careful usage of the lock ordering
382    /// types. Any type implementing this must take care to use the appropriate
383    /// wrapper API and have alternative compilation configurations that enforce
384    /// the lock order.
385    pub unsafe trait DisabledLockWrapper {}
386
387    fn disabled<T, L>(Locked(t, PhantomData): Locked<T, L>) -> Locked<T, Unlocked> {
388        Locked(t, PhantomData)
389    }
390
391    /// Provides an API with the same shape as [`Locked`] for any type
392    /// implementing [`LockedWrapper`] *that effectively disables lock ordering
393    /// checks*.
394    pub trait LockedDisabledWrapperApi<T, L>: LockedWrapper<T, L> + DisabledLockWrapper
395    where
396        T: Deref,
397        T::Target: Sized,
398    {
399        /// Like [`Locked::lock`].
400        fn lock<'a, M>(&'a mut self) -> <T::Target as LockFor<M>>::Guard<'a>
401        where
402            T: 'a,
403            T::Target: LockFor<M>,
404            L: LockBefore<M> + 'a,
405        {
406            self.get_mut().lock::<M>()
407        }
408
409        /// Like [`Locked::lock_and`].
410        fn lock_and<'a, M>(
411            &'a mut self,
412        ) -> (<T::Target as LockFor<M>>::Guard<'a>, Self::AtLockLevel<'a, Unlocked>)
413        where
414            T::Target: LockFor<M>,
415            L: LockBefore<M> + 'a,
416        {
417            let (guard, locked) = self.get_mut().lock_and::<M>();
418            (guard, Self::wrap(disabled(locked)))
419        }
420
421        /// Like [`Locked::lock_with`].
422        fn lock_with<'a, M, X>(&'a mut self, f: impl FnOnce(&T::Target) -> &X) -> X::Guard<'a>
423        where
424            T: 'a,
425            X: LockFor<M>,
426            L: LockBefore<M> + 'a,
427        {
428            self.get_mut().lock_with::<M, X>(f)
429        }
430
431        /// Like [`Locked::lock_with_and`].
432        fn lock_with_and<'a, M, X>(
433            &'a mut self,
434            f: impl FnOnce(&T::Target) -> &X,
435        ) -> (X::Guard<'a>, Self::AtLockLevel<'a, Unlocked>)
436        where
437            X: LockFor<M>,
438            L: LockBefore<M> + 'a,
439        {
440            let (guard, locked) = self.get_mut().lock_with_and::<M, X>(f);
441            (guard, Self::wrap(disabled(locked)))
442        }
443
444        /// Like [`Locked::read_lock`].
445        fn read_lock<'a, M>(&'a mut self) -> <T::Target as RwLockFor<M>>::ReadGuard<'a>
446        where
447            T: 'a,
448            T::Target: RwLockFor<M>,
449            L: LockBefore<M> + 'a,
450        {
451            self.get_mut().read_lock::<M>()
452        }
453
454        /// Like [`Locked::read_lock_and`].
455        fn read_lock_and<'a, M>(
456            &'a mut self,
457        ) -> (<T::Target as RwLockFor<M>>::ReadGuard<'a>, Self::AtLockLevel<'a, Unlocked>)
458        where
459            T::Target: RwLockFor<M>,
460            L: LockBefore<M> + 'a,
461        {
462            let (guard, locked) = self.get_mut().read_lock_and::<M>();
463            (guard, Self::wrap(disabled(locked)))
464        }
465
466        /// Like [`Locked::read_lock_with`].
467        fn read_lock_with<'a, M, X>(
468            &'a mut self,
469            f: impl FnOnce(&T::Target) -> &X,
470        ) -> X::ReadGuard<'a>
471        where
472            T: 'a,
473            X: RwLockFor<M>,
474            L: LockBefore<M> + 'a,
475        {
476            self.get_mut().read_lock_with::<M, X>(f)
477        }
478
479        /// Like [`Locked::read_lock_with_and`].
480        fn read_lock_with_and<'a, M, X>(
481            &'a mut self,
482            f: impl FnOnce(&T::Target) -> &X,
483        ) -> (X::ReadGuard<'a>, Self::AtLockLevel<'a, Unlocked>)
484        where
485            X: RwLockFor<M>,
486            L: LockBefore<M> + 'a,
487        {
488            let (guard, locked) = self.get_mut().read_lock_with_and::<M, X>(f);
489            (guard, Self::wrap(disabled(locked)))
490        }
491
492        /// Like [`Locked::write_lock`].
493        fn write_lock<'a, M>(&'a mut self) -> <T::Target as RwLockFor<M>>::WriteGuard<'a>
494        where
495            T: 'a,
496            T::Target: RwLockFor<M>,
497            L: LockBefore<M> + 'a,
498        {
499            self.get_mut().write_lock::<M>()
500        }
501
502        /// Like [`Locked::write_lock_and`].
503        fn write_lock_and<'a, M>(
504            &'a mut self,
505        ) -> (<T::Target as RwLockFor<M>>::WriteGuard<'a>, Self::AtLockLevel<'a, Unlocked>)
506        where
507            T::Target: RwLockFor<M>,
508            L: LockBefore<M> + 'a,
509        {
510            let (guard, locked) = self.get_mut().write_lock_and::<M>();
511            (guard, Self::wrap(disabled(locked)))
512        }
513
514        /// Like [`Locked::write_lock_with`].
515        fn write_lock_with<'a, M, X>(
516            &'a mut self,
517            f: impl FnOnce(&T::Target) -> &X,
518        ) -> X::WriteGuard<'a>
519        where
520            T: 'a,
521            X: RwLockFor<M>,
522            L: LockBefore<M> + 'a,
523        {
524            self.get_mut().write_lock_with::<M, X>(f)
525        }
526
527        /// Like [`Locked::write_lock_with_and`].
528        fn write_lock_with_and<'a, M, X>(
529            &'a mut self,
530            f: impl FnOnce(&T::Target) -> &X,
531        ) -> (X::WriteGuard<'a>, Self::AtLockLevel<'a, Unlocked>)
532        where
533            X: RwLockFor<M>,
534            L: LockBefore<M> + 'a,
535        {
536            let (guard, locked) = self.get_mut().write_lock_with_and::<M, X>(f);
537            (guard, Self::wrap(disabled(locked)))
538        }
539
540        /// Like [`Locked::as_owned`].
541        fn as_owned(&mut self) -> Self::AtLockLevel<'_, L> {
542            Self::wrap(self.get_mut().cast_with(|s| s))
543        }
544
545        /// Like [`Locked::cast`].
546        fn cast<'a, R>(&'a mut self) -> Self::CastWrapper<&'a R>
547        where
548            T: 'a,
549            L: 'a,
550            T::Target: AsRef<R>,
551        {
552            Self::wrap_cast(self.get_mut().cast_with(AsRef::as_ref))
553        }
554
555        /// Like [`Locked::cast_with`]
556        fn cast_with<'a, R>(
557            &'a mut self,
558            f: impl FnOnce(&T::Target) -> &R,
559        ) -> Self::CastWrapper<&'a R>
560        where
561            T: 'a,
562            L: 'a,
563        {
564            Self::wrap_cast(self.get_mut().cast_with::<R>(f))
565        }
566
567        /// Like [`Locked::cast_locked`].
568        fn cast_locked<'a, M>(&'a mut self) -> Self::AtLockLevel<'a, Unlocked>
569        where
570            L: LockBefore<M> + 'a,
571        {
572            Self::wrap(disabled(self.get_mut().cast_locked::<M>()))
573        }
574
575        /// Like [`Locked::copied`].
576        fn copied(&self) -> T::Target
577        where
578            T::Target: Copy,
579        {
580            self.get().copied()
581        }
582
583        /// Like [`Locked::adopt`].
584        fn adopt<'a, N>(
585            &'a mut self,
586            n: &'a N,
587        ) -> Self::CastWrapper<OwnedTupleWrapper<&'a T::Target, &'a N>>
588        where
589            T: 'a,
590            L: 'a,
591        {
592            Self::wrap_cast(self.get_mut().adopt(n))
593        }
594
595        /// Like [`Locked::cast_left`].
596        fn cast_left<'a, X, A: Deref + 'a, B: Deref + 'a, F: FnOnce(&A::Target) -> &X>(
597            &'a mut self,
598            f: F,
599        ) -> Self::CastWrapper<OwnedTupleWrapper<&'a X, &'a B::Target>>
600        where
601            L: 'a,
602            T: Deref<Target = TupleWrapper<A, B>> + 'a,
603        {
604            Self::wrap_cast(self.get_mut().cast_left(f))
605        }
606
607        /// Like [`Locked::cast_right`].
608        fn cast_right<'a, X, A: Deref + 'a, B: Deref + 'a, F: FnOnce(&B::Target) -> &X>(
609            &'a mut self,
610            f: F,
611        ) -> Self::CastWrapper<OwnedTupleWrapper<&'a A::Target, &'a X>>
612        where
613            L: 'a,
614            T: Deref<Target = TupleWrapper<A, B>> + 'a,
615        {
616            Self::wrap_cast(self.get_mut().cast_right(f))
617        }
618
619        /// Like [`Locked::replace`].
620        fn replace<'a, N>(&'a mut self, n: &'a N) -> Self::CastWrapper<&'a N>
621        where
622            L: 'a,
623            T: 'a,
624        {
625            Self::wrap_cast(self.get_mut().replace(n))
626        }
627    }
628
629    impl<T, L, O> LockedDisabledWrapperApi<T, L> for O
630    where
631        T: Deref,
632        T::Target: Sized,
633        O: LockedWrapper<T, L> + DisabledLockWrapper,
634    {
635    }
636}