@@ -14,55 +14,7 @@ use core::pin::Pin;
1414/// when a guard goes out of scope. It also provides a safe and convenient way to access the data
1515/// protected by the lock.
1616#[ must_use = "the lock unlocks immediately when the guard is unused" ]
17- pub struct GuardMut < ' a , L : Lock + ?Sized > {
18- pub ( crate ) guard : Guard < ' a , L > ,
19- }
20-
21- // SAFETY: `GuardMut` is sync when the data protected by the lock is also sync. This is more
22- // conservative than the default compiler implementation; more details can be found on
23- // https://github.com/rust-lang/rust/issues/41622 -- it refers to `MutexGuard` from the standard
24- // library.
25- unsafe impl < L > Sync for GuardMut < ' _ , L >
26- where
27- L : Lock + ?Sized ,
28- L :: Inner : Sync ,
29- {
30- }
31-
32- impl < L : Lock + ?Sized > core:: ops:: Deref for GuardMut < ' _ , L > {
33- type Target = L :: Inner ;
34-
35- fn deref ( & self ) -> & Self :: Target {
36- self . guard . deref ( )
37- }
38- }
39-
40- impl < L : Lock + ?Sized > core:: ops:: DerefMut for GuardMut < ' _ , L > {
41- fn deref_mut ( & mut self ) -> & mut L :: Inner {
42- // SAFETY: The caller owns the lock, so it is safe to deref the protected data.
43- unsafe { & mut * self . guard . lock . locked_data ( ) . get ( ) }
44- }
45- }
46-
47- impl < ' a , L : Lock + ?Sized > GuardMut < ' a , L > {
48- /// Constructs a new lock guard.
49- ///
50- /// # Safety
51- ///
52- /// The caller must ensure that it owns the lock.
53- pub ( crate ) unsafe fn new ( lock : & ' a L , context : L :: GuardContext ) -> Self {
54- // SAFETY: The safety requirements for this function satisfy the `Guard::new` ones.
55- Self {
56- guard : unsafe { Guard :: new ( lock, context) } ,
57- }
58- }
59- }
60-
61- /// Allows mutual exclusion primitives that implement the [`Lock`] trait to automatically unlock
62- /// when a guard goes out of scope. It also provides a safe and convenient way to immutably access
63- /// the data protected by the lock.
64- #[ must_use = "the lock unlocks immediately when the guard is unused" ]
65- pub struct Guard < ' a , L : Lock + ?Sized > {
17+ pub struct Guard < ' a , L : Lock < M > + ?Sized , M = WriteLock > {
6618 pub ( crate ) lock : & ' a L ,
6719 pub ( crate ) context : L :: GuardContext ,
6820}
@@ -71,14 +23,14 @@ pub struct Guard<'a, L: Lock + ?Sized> {
7123// conservative than the default compiler implementation; more details can be found on
7224// https://github.com/rust-lang/rust/issues/41622 -- it refers to `MutexGuard` from the standard
7325// library.
74- unsafe impl < L > Sync for Guard < ' _ , L >
26+ unsafe impl < L , M > Sync for Guard < ' _ , L , M >
7527where
76- L : Lock + ?Sized ,
28+ L : Lock < M > + ?Sized ,
7729 L :: Inner : Sync ,
7830{
7931}
8032
81- impl < L : Lock + ?Sized > core:: ops:: Deref for Guard < ' _ , L > {
33+ impl < L : Lock < M > + ?Sized , M > core:: ops:: Deref for Guard < ' _ , L , M > {
8234 type Target = L :: Inner ;
8335
8436 fn deref ( & self ) -> & Self :: Target {
@@ -87,14 +39,21 @@ impl<L: Lock + ?Sized> core::ops::Deref for Guard<'_, L> {
8739 }
8840}
8941
90- impl < L : Lock + ?Sized > Drop for Guard < ' _ , L > {
42+ impl < L : Lock < WriteLock > + ?Sized > core:: ops:: DerefMut for Guard < ' _ , L , WriteLock > {
43+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
44+ // SAFETY: The caller owns the lock, so it is safe to deref the protected data.
45+ unsafe { & mut * self . lock . locked_data ( ) . get ( ) }
46+ }
47+ }
48+
49+ impl < L : Lock < M > + ?Sized , M > Drop for Guard < ' _ , L , M > {
9150 fn drop ( & mut self ) {
9251 // SAFETY: The caller owns the lock, so it is safe to unlock it.
9352 unsafe { self . lock . unlock ( & mut self . context ) } ;
9453 }
9554}
9655
97- impl < ' a , L : Lock + ?Sized > Guard < ' a , L > {
56+ impl < ' a , L : Lock < M > + ?Sized , M > Guard < ' a , L , M > {
9857 /// Constructs a new immutable lock guard.
9958 ///
10059 /// # Safety
@@ -105,16 +64,26 @@ impl<'a, L: Lock + ?Sized> Guard<'a, L> {
10564 }
10665}
10766
67+ /// A marker for locks that only allow reading.
68+ pub struct ReadLock ;
69+
70+ /// A marker for locks that allow reading and writing.
71+ pub struct WriteLock ;
72+
10873/// A generic mutual exclusion primitive.
10974///
110- /// [`Guard`] and [`GuardMut`] are written such that any mutual exclusion primitive that can
111- /// implement this trait can also benefit from having an automatic way to unlock itself.
75+ /// [`Guard`] is written such that any mutual exclusion primitive that can implement this trait can
76+ /// also benefit from having an automatic way to unlock itself.
11277///
11378/// # Safety
11479///
115- /// Implementers of this trait must ensure that only one thread/CPU may access the protected data
116- /// once the lock is held, that is, between calls to `lock_noguard` and `unlock`.
117- pub unsafe trait Lock {
80+ /// - Implementers of this trait with the [`WriteLock`] marker must ensure that only one thread/CPU
81+ /// may access the protected data once the lock is held, that is, between calls to `lock_noguard`
82+ /// and `unlock`.
83+ /// - Implementers of all other markers must ensure that a mutable reference to the protected data
84+ /// is not active in any thread/CPU because at least one shared refence is active between calls
85+ /// to `lock_noguard` and `unlock`.
86+ pub unsafe trait Lock < M = WriteLock > {
11887 /// The type of the data protected by the lock.
11988 type Inner : ?Sized ;
12089
@@ -147,7 +116,7 @@ pub unsafe trait Lock {
147116}
148117
149118/// A generic mutual exclusion primitive that can be instantiated generically.
150- pub trait CreatableLock : Lock {
119+ pub trait CreatableLock < M = WriteLock > : Lock < M > {
151120 /// Constructs a new instance of the lock.
152121 ///
153122 /// # Safety
0 commit comments