77//! other constructs to work on generic locking primitives.
88
99use super :: NeedsLockClass ;
10- use crate :: { bindings, str:: CStr } ;
10+ use crate :: { bindings, str:: CStr , Bool , False , True } ;
1111use core:: pin:: Pin ;
1212
1313/// Allows mutual exclusion primitives that implement the [`Lock`] trait to automatically unlock
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 Guard < ' a , L : Lock < M > + ?Sized , M = WriteLock > {
17+ pub struct Guard < ' a , L : Lock < I > + ?Sized , I : LockInfo = WriteLock > {
1818 pub ( crate ) lock : & ' a L ,
1919 pub ( crate ) context : L :: GuardContext ,
2020}
@@ -23,14 +23,15 @@ pub struct Guard<'a, L: Lock<M> + ?Sized, M = WriteLock> {
2323// conservative than the default compiler implementation; more details can be found on
2424// https://github.com/rust-lang/rust/issues/41622 -- it refers to `MutexGuard` from the standard
2525// library.
26- unsafe impl < L , M > Sync for Guard < ' _ , L , M >
26+ unsafe impl < L , I > Sync for Guard < ' _ , L , I >
2727where
28- L : Lock < M > + ?Sized ,
28+ L : Lock < I > + ?Sized ,
2929 L :: Inner : Sync ,
30+ I : LockInfo ,
3031{
3132}
3233
33- impl < L : Lock < M > + ?Sized , M > core:: ops:: Deref for Guard < ' _ , L , M > {
34+ impl < L : Lock < I > + ?Sized , I : LockInfo > core:: ops:: Deref for Guard < ' _ , L , I > {
3435 type Target = L :: Inner ;
3536
3637 fn deref ( & self ) -> & Self :: Target {
@@ -39,21 +40,21 @@ impl<L: Lock<M> + ?Sized, M> core::ops::Deref for Guard<'_, L, M> {
3940 }
4041}
4142
42- impl < L : Lock < WriteLock > + ?Sized > core:: ops:: DerefMut for Guard < ' _ , L , WriteLock > {
43+ impl < L : Lock < I > + ?Sized , I : LockInfo < Writable = True > > core:: ops:: DerefMut for Guard < ' _ , L , I > {
4344 fn deref_mut ( & mut self ) -> & mut Self :: Target {
4445 // SAFETY: The caller owns the lock, so it is safe to deref the protected data.
4546 unsafe { & mut * self . lock . locked_data ( ) . get ( ) }
4647 }
4748}
4849
49- impl < L : Lock < M > + ?Sized , M > Drop for Guard < ' _ , L , M > {
50+ impl < L : Lock < I > + ?Sized , I : LockInfo > Drop for Guard < ' _ , L , I > {
5051 fn drop ( & mut self ) {
5152 // SAFETY: The caller owns the lock, so it is safe to unlock it.
5253 unsafe { self . lock . unlock ( & mut self . context ) } ;
5354 }
5455}
5556
56- impl < ' a , L : Lock < M > + ?Sized , M > Guard < ' a , L , M > {
57+ impl < ' a , L : Lock < I > + ?Sized , I : LockInfo > Guard < ' a , L , I > {
5758 /// Constructs a new immutable lock guard.
5859 ///
5960 /// # Safety
@@ -64,11 +65,23 @@ impl<'a, L: Lock<M> + ?Sized, M> Guard<'a, L, M> {
6465 }
6566}
6667
68+ /// Specifies properties of a lock.
69+ pub trait LockInfo {
70+ /// Determines if the data protected by a lock is writable.
71+ type Writable : Bool ;
72+ }
73+
6774/// A marker for locks that only allow reading.
6875pub struct ReadLock ;
76+ impl LockInfo for ReadLock {
77+ type Writable = False ;
78+ }
6979
7080/// A marker for locks that allow reading and writing.
7181pub struct WriteLock ;
82+ impl LockInfo for WriteLock {
83+ type Writable = True ;
84+ }
7285
7386/// A generic mutual exclusion primitive.
7487///
@@ -83,7 +96,7 @@ pub struct WriteLock;
8396/// - Implementers of all other markers must ensure that a mutable reference to the protected data
8497/// is not active in any thread/CPU because at least one shared refence is active between calls
8598/// to `lock_noguard` and `unlock`.
86- pub unsafe trait Lock < M = WriteLock > {
99+ pub unsafe trait Lock < I : LockInfo = WriteLock > {
87100 /// The type of the data protected by the lock.
88101 type Inner : ?Sized ;
89102
@@ -116,13 +129,16 @@ pub unsafe trait Lock<M = WriteLock> {
116129}
117130
118131/// A generic mutual exclusion primitive that can be instantiated generically.
119- pub trait CreatableLock < M = WriteLock > : Lock < M > {
132+ pub trait CreatableLock {
133+ /// The type of the argument passed to [`CreatableLock::new_lock`].
134+ type CreateArgType : ?Sized ;
135+
120136 /// Constructs a new instance of the lock.
121137 ///
122138 /// # Safety
123139 ///
124140 /// The caller must call [`CreatableLock::init_lock`] before using the lock.
125- unsafe fn new_lock ( data : Self :: Inner ) -> Self ;
141+ unsafe fn new_lock ( data : Self :: CreateArgType ) -> Self ;
126142
127143 /// Initialises the lock type instance so that it can be safely used.
128144 ///
0 commit comments