1 use crate::sync::batch_semaphore::{Semaphore, TryAcquireError};
2 use crate::sync::mutex::TryLockError;
3 use std::cell::UnsafeCell;
4 use std::marker;
5 use std::marker::PhantomData;
6 use std::mem::ManuallyDrop;
7 use std::sync::Arc;
8 
9 pub(crate) mod owned_read_guard;
10 pub(crate) mod owned_write_guard;
11 pub(crate) mod owned_write_guard_mapped;
12 pub(crate) mod read_guard;
13 pub(crate) mod write_guard;
14 pub(crate) mod write_guard_mapped;
15 pub(crate) use owned_read_guard::OwnedRwLockReadGuard;
16 pub(crate) use owned_write_guard::OwnedRwLockWriteGuard;
17 pub(crate) use owned_write_guard_mapped::OwnedRwLockMappedWriteGuard;
18 pub(crate) use read_guard::RwLockReadGuard;
19 pub(crate) use write_guard::RwLockWriteGuard;
20 pub(crate) use write_guard_mapped::RwLockMappedWriteGuard;
21 
22 #[cfg(not(loom))]
23 const MAX_READS: u32 = std::u32::MAX >> 3;
24 
25 #[cfg(loom)]
26 const MAX_READS: u32 = 10;
27 
28 /// An asynchronous reader-writer lock.
29 ///
30 /// This type of lock allows a number of readers or at most one writer at any
31 /// point in time. The write portion of this lock typically allows modification
32 /// of the underlying data (exclusive access) and the read portion of this lock
33 /// typically allows for read-only access (shared access).
34 ///
35 /// In comparison, a [`Mutex`] does not distinguish between readers or writers
36 /// that acquire the lock, therefore causing any tasks waiting for the lock to
37 /// become available to yield. An `RwLock` will allow any number of readers to
38 /// acquire the lock as long as a writer is not holding the lock.
39 ///
40 /// The priority policy of Tokio's read-write lock is _fair_ (or
41 /// [_write-preferring_]), in order to ensure that readers cannot starve
42 /// writers. Fairness is ensured using a first-in, first-out queue for the tasks
43 /// awaiting the lock; if a task that wishes to acquire the write lock is at the
44 /// head of the queue, read locks will not be given out until the write lock has
45 /// been released. This is in contrast to the Rust standard library's
46 /// `std::sync::RwLock`, where the priority policy is dependent on the
47 /// operating system's implementation.
48 ///
49 /// The type parameter `T` represents the data that this lock protects. It is
50 /// required that `T` satisfies [`Send`] to be shared across threads. The RAII guards
51 /// returned from the locking methods implement [`Deref`](trait@std::ops::Deref)
52 /// (and [`DerefMut`](trait@std::ops::DerefMut)
53 /// for the `write` methods) to allow access to the content of the lock.
54 ///
55 /// # Examples
56 ///
57 /// ```
58 /// use tokio::sync::RwLock;
59 ///
60 /// #[tokio::main]
61 /// async fn main() {
62 ///     let lock = RwLock::new(5);
63 ///
64 ///     // many reader locks can be held at once
65 ///     {
66 ///         let r1 = lock.read().await;
67 ///         let r2 = lock.read().await;
68 ///         assert_eq!(*r1, 5);
69 ///         assert_eq!(*r2, 5);
70 ///     } // read locks are dropped at this point
71 ///
72 ///     // only one write lock may be held, however
73 ///     {
74 ///         let mut w = lock.write().await;
75 ///         *w += 1;
76 ///         assert_eq!(*w, 6);
77 ///     } // write lock is dropped here
78 /// }
79 /// ```
80 ///
81 /// [`Mutex`]: struct@super::Mutex
82 /// [`RwLock`]: struct@RwLock
83 /// [`RwLockReadGuard`]: struct@RwLockReadGuard
84 /// [`RwLockWriteGuard`]: struct@RwLockWriteGuard
85 /// [`Send`]: trait@std::marker::Send
86 /// [_write-preferring_]: https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock#Priority_policies
87 #[derive(Debug)]
88 pub struct RwLock<T: ?Sized> {
89     // maximum number of concurrent readers
90     mr: u32,
91 
92     //semaphore to coordinate read and write access to T
93     s: Semaphore,
94 
95     //inner data T
96     c: UnsafeCell<T>,
97 }
98 
99 #[test]
100 #[cfg(not(loom))]
bounds()101 fn bounds() {
102     fn check_send<T: Send>() {}
103     fn check_sync<T: Sync>() {}
104     fn check_unpin<T: Unpin>() {}
105     // This has to take a value, since the async fn's return type is unnameable.
106     fn check_send_sync_val<T: Send + Sync>(_t: T) {}
107 
108     check_send::<RwLock<u32>>();
109     check_sync::<RwLock<u32>>();
110     check_unpin::<RwLock<u32>>();
111 
112     check_send::<RwLockReadGuard<'_, u32>>();
113     check_sync::<RwLockReadGuard<'_, u32>>();
114     check_unpin::<RwLockReadGuard<'_, u32>>();
115 
116     check_send::<OwnedRwLockReadGuard<u32, i32>>();
117     check_sync::<OwnedRwLockReadGuard<u32, i32>>();
118     check_unpin::<OwnedRwLockReadGuard<u32, i32>>();
119 
120     check_send::<RwLockWriteGuard<'_, u32>>();
121     check_sync::<RwLockWriteGuard<'_, u32>>();
122     check_unpin::<RwLockWriteGuard<'_, u32>>();
123 
124     check_send::<RwLockMappedWriteGuard<'_, u32>>();
125     check_sync::<RwLockMappedWriteGuard<'_, u32>>();
126     check_unpin::<RwLockMappedWriteGuard<'_, u32>>();
127 
128     check_send::<OwnedRwLockWriteGuard<u32>>();
129     check_sync::<OwnedRwLockWriteGuard<u32>>();
130     check_unpin::<OwnedRwLockWriteGuard<u32>>();
131 
132     check_send::<OwnedRwLockMappedWriteGuard<u32, i32>>();
133     check_sync::<OwnedRwLockMappedWriteGuard<u32, i32>>();
134     check_unpin::<OwnedRwLockMappedWriteGuard<u32, i32>>();
135 
136     let rwlock = Arc::new(RwLock::new(0));
137     check_send_sync_val(rwlock.read());
138     check_send_sync_val(Arc::clone(&rwlock).read_owned());
139     check_send_sync_val(rwlock.write());
140     check_send_sync_val(Arc::clone(&rwlock).write_owned());
141 }
142 
143 // As long as T: Send + Sync, it's fine to send and share RwLock<T> between threads.
144 // If T were not Send, sending and sharing a RwLock<T> would be bad, since you can access T through
145 // RwLock<T>.
146 unsafe impl<T> Send for RwLock<T> where T: ?Sized + Send {}
147 unsafe impl<T> Sync for RwLock<T> where T: ?Sized + Send + Sync {}
148 // NB: These impls need to be explicit since we're storing a raw pointer.
149 // Safety: Stores a raw pointer to `T`, so if `T` is `Sync`, the lock guard over
150 // `T` is `Send`.
151 unsafe impl<T> Send for RwLockReadGuard<'_, T> where T: ?Sized + Sync {}
152 unsafe impl<T> Sync for RwLockReadGuard<'_, T> where T: ?Sized + Send + Sync {}
153 // T is required to be `Send` because an OwnedRwLockReadGuard can be used to drop the value held in
154 // the RwLock, unlike RwLockReadGuard.
155 unsafe impl<T, U> Send for OwnedRwLockReadGuard<T, U>
156 where
157     T: ?Sized + Send + Sync,
158     U: ?Sized + Sync,
159 {
160 }
161 unsafe impl<T, U> Sync for OwnedRwLockReadGuard<T, U>
162 where
163     T: ?Sized + Send + Sync,
164     U: ?Sized + Send + Sync,
165 {
166 }
167 unsafe impl<T> Sync for RwLockWriteGuard<'_, T> where T: ?Sized + Send + Sync {}
168 unsafe impl<T> Sync for OwnedRwLockWriteGuard<T> where T: ?Sized + Send + Sync {}
169 unsafe impl<T> Sync for RwLockMappedWriteGuard<'_, T> where T: ?Sized + Send + Sync {}
170 unsafe impl<T, U> Sync for OwnedRwLockMappedWriteGuard<T, U>
171 where
172     T: ?Sized + Send + Sync,
173     U: ?Sized + Send + Sync,
174 {
175 }
176 // Safety: Stores a raw pointer to `T`, so if `T` is `Sync`, the lock guard over
177 // `T` is `Send` - but since this is also provides mutable access, we need to
178 // make sure that `T` is `Send` since its value can be sent across thread
179 // boundaries.
180 unsafe impl<T> Send for RwLockWriteGuard<'_, T> where T: ?Sized + Send + Sync {}
181 unsafe impl<T> Send for OwnedRwLockWriteGuard<T> where T: ?Sized + Send + Sync {}
182 unsafe impl<T> Send for RwLockMappedWriteGuard<'_, T> where T: ?Sized + Send + Sync {}
183 unsafe impl<T, U> Send for OwnedRwLockMappedWriteGuard<T, U>
184 where
185     T: ?Sized + Send + Sync,
186     U: ?Sized + Send + Sync,
187 {
188 }
189 
190 impl<T: ?Sized> RwLock<T> {
191     /// Creates a new instance of an `RwLock<T>` which is unlocked.
192     ///
193     /// # Examples
194     ///
195     /// ```
196     /// use tokio::sync::RwLock;
197     ///
198     /// let lock = RwLock::new(5);
199     /// ```
new(value: T) -> RwLock<T> where T: Sized,200     pub fn new(value: T) -> RwLock<T>
201     where
202         T: Sized,
203     {
204         RwLock {
205             mr: MAX_READS,
206             c: UnsafeCell::new(value),
207             s: Semaphore::new(MAX_READS as usize),
208         }
209     }
210 
211     /// Creates a new instance of an `RwLock<T>` which is unlocked
212     /// and allows a maximum of `max_reads` concurrent readers.
213     ///
214     /// # Examples
215     ///
216     /// ```
217     /// use tokio::sync::RwLock;
218     ///
219     /// let lock = RwLock::with_max_readers(5, 1024);
220     /// ```
221     ///
222     /// # Panics
223     ///
224     /// Panics if `max_reads` is more than `u32::MAX >> 3`.
with_max_readers(value: T, max_reads: u32) -> RwLock<T> where T: Sized,225     pub fn with_max_readers(value: T, max_reads: u32) -> RwLock<T>
226     where
227         T: Sized,
228     {
229         assert!(
230             max_reads <= MAX_READS,
231             "a RwLock may not be created with more than {} readers",
232             MAX_READS
233         );
234         RwLock {
235             mr: max_reads,
236             c: UnsafeCell::new(value),
237             s: Semaphore::new(max_reads as usize),
238         }
239     }
240 
241     /// Creates a new instance of an `RwLock<T>` which is unlocked.
242     ///
243     /// # Examples
244     ///
245     /// ```
246     /// use tokio::sync::RwLock;
247     ///
248     /// static LOCK: RwLock<i32> = RwLock::const_new(5);
249     /// ```
250     #[cfg(all(feature = "parking_lot", not(all(loom, test))))]
251     #[cfg_attr(docsrs, doc(cfg(feature = "parking_lot")))]
const_new(value: T) -> RwLock<T> where T: Sized,252     pub const fn const_new(value: T) -> RwLock<T>
253     where
254         T: Sized,
255     {
256         RwLock {
257             mr: MAX_READS,
258             c: UnsafeCell::new(value),
259             s: Semaphore::const_new(MAX_READS as usize),
260         }
261     }
262 
263     /// Creates a new instance of an `RwLock<T>` which is unlocked
264     /// and allows a maximum of `max_reads` concurrent readers.
265     ///
266     /// # Examples
267     ///
268     /// ```
269     /// use tokio::sync::RwLock;
270     ///
271     /// static LOCK: RwLock<i32> = RwLock::const_with_max_readers(5, 1024);
272     /// ```
273     #[cfg(all(feature = "parking_lot", not(all(loom, test))))]
274     #[cfg_attr(docsrs, doc(cfg(feature = "parking_lot")))]
const_with_max_readers(value: T, mut max_reads: u32) -> RwLock<T> where T: Sized,275     pub const fn const_with_max_readers(value: T, mut max_reads: u32) -> RwLock<T>
276     where
277         T: Sized,
278     {
279         max_reads &= MAX_READS;
280         RwLock {
281             mr: max_reads,
282             c: UnsafeCell::new(value),
283             s: Semaphore::const_new(max_reads as usize),
284         }
285     }
286 
287     /// Locks this `RwLock` with shared read access, causing the current task
288     /// to yield until the lock has been acquired.
289     ///
290     /// The calling task will yield until there are no writers which hold the
291     /// lock. There may be other readers inside the lock when the task resumes.
292     ///
293     /// Note that under the priority policy of [`RwLock`], read locks are not
294     /// granted until prior write locks, to prevent starvation. Therefore
295     /// deadlock may occur if a read lock is held by the current task, a write
296     /// lock attempt is made, and then a subsequent read lock attempt is made
297     /// by the current task.
298     ///
299     /// Returns an RAII guard which will drop this read access of the `RwLock`
300     /// when dropped.
301     ///
302     /// # Cancel safety
303     ///
304     /// This method uses a queue to fairly distribute locks in the order they
305     /// were requested. Cancelling a call to `read` makes you lose your place in
306     /// the queue.
307     ///
308     /// # Examples
309     ///
310     /// ```
311     /// use std::sync::Arc;
312     /// use tokio::sync::RwLock;
313     ///
314     /// #[tokio::main]
315     /// async fn main() {
316     ///     let lock = Arc::new(RwLock::new(1));
317     ///     let c_lock = lock.clone();
318     ///
319     ///     let n = lock.read().await;
320     ///     assert_eq!(*n, 1);
321     ///
322     ///     tokio::spawn(async move {
323     ///         // While main has an active read lock, we acquire one too.
324     ///         let r = c_lock.read().await;
325     ///         assert_eq!(*r, 1);
326     ///     }).await.expect("The spawned task has panicked");
327     ///
328     ///     // Drop the guard after the spawned task finishes.
329     ///     drop(n);
330     ///}
331     /// ```
read(&self) -> RwLockReadGuard<'_, T>332     pub async fn read(&self) -> RwLockReadGuard<'_, T> {
333         self.s.acquire(1).await.unwrap_or_else(|_| {
334             // The semaphore was closed. but, we never explicitly close it, and we have a
335             // handle to it through the Arc, which means that this can never happen.
336             unreachable!()
337         });
338         RwLockReadGuard {
339             s: &self.s,
340             data: self.c.get(),
341             marker: marker::PhantomData,
342         }
343     }
344 
345     /// Locks this `RwLock` with shared read access, causing the current task
346     /// to yield until the lock has been acquired.
347     ///
348     /// The calling task will yield until there are no writers which hold the
349     /// lock. There may be other readers inside the lock when the task resumes.
350     ///
351     /// This method is identical to [`RwLock::read`], except that the returned
352     /// guard references the `RwLock` with an [`Arc`] rather than by borrowing
353     /// it. Therefore, the `RwLock` must be wrapped in an `Arc` to call this
354     /// method, and the guard will live for the `'static` lifetime, as it keeps
355     /// the `RwLock` alive by holding an `Arc`.
356     ///
357     /// Note that under the priority policy of [`RwLock`], read locks are not
358     /// granted until prior write locks, to prevent starvation. Therefore
359     /// deadlock may occur if a read lock is held by the current task, a write
360     /// lock attempt is made, and then a subsequent read lock attempt is made
361     /// by the current task.
362     ///
363     /// Returns an RAII guard which will drop this read access of the `RwLock`
364     /// when dropped.
365     ///
366     /// # Cancel safety
367     ///
368     /// This method uses a queue to fairly distribute locks in the order they
369     /// were requested. Cancelling a call to `read_owned` makes you lose your
370     /// place in the queue.
371     ///
372     /// # Examples
373     ///
374     /// ```
375     /// use std::sync::Arc;
376     /// use tokio::sync::RwLock;
377     ///
378     /// #[tokio::main]
379     /// async fn main() {
380     ///     let lock = Arc::new(RwLock::new(1));
381     ///     let c_lock = lock.clone();
382     ///
383     ///     let n = lock.read_owned().await;
384     ///     assert_eq!(*n, 1);
385     ///
386     ///     tokio::spawn(async move {
387     ///         // While main has an active read lock, we acquire one too.
388     ///         let r = c_lock.read_owned().await;
389     ///         assert_eq!(*r, 1);
390     ///     }).await.expect("The spawned task has panicked");
391     ///
392     ///     // Drop the guard after the spawned task finishes.
393     ///     drop(n);
394     ///}
395     /// ```
read_owned(self: Arc<Self>) -> OwnedRwLockReadGuard<T>396     pub async fn read_owned(self: Arc<Self>) -> OwnedRwLockReadGuard<T> {
397         self.s.acquire(1).await.unwrap_or_else(|_| {
398             // The semaphore was closed. but, we never explicitly close it, and we have a
399             // handle to it through the Arc, which means that this can never happen.
400             unreachable!()
401         });
402         OwnedRwLockReadGuard {
403             data: self.c.get(),
404             lock: ManuallyDrop::new(self),
405             _p: PhantomData,
406         }
407     }
408 
409     /// Attempts to acquire this `RwLock` with shared read access.
410     ///
411     /// If the access couldn't be acquired immediately, returns [`TryLockError`].
412     /// Otherwise, an RAII guard is returned which will release read access
413     /// when dropped.
414     ///
415     /// [`TryLockError`]: TryLockError
416     ///
417     /// # Examples
418     ///
419     /// ```
420     /// use std::sync::Arc;
421     /// use tokio::sync::RwLock;
422     ///
423     /// #[tokio::main]
424     /// async fn main() {
425     ///     let lock = Arc::new(RwLock::new(1));
426     ///     let c_lock = lock.clone();
427     ///
428     ///     let v = lock.try_read().unwrap();
429     ///     assert_eq!(*v, 1);
430     ///
431     ///     tokio::spawn(async move {
432     ///         // While main has an active read lock, we acquire one too.
433     ///         let n = c_lock.read().await;
434     ///         assert_eq!(*n, 1);
435     ///     }).await.expect("The spawned task has panicked");
436     ///
437     ///     // Drop the guard when spawned task finishes.
438     ///     drop(v);
439     /// }
440     /// ```
try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError>441     pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError> {
442         match self.s.try_acquire(1) {
443             Ok(permit) => permit,
444             Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
445             Err(TryAcquireError::Closed) => unreachable!(),
446         }
447 
448         Ok(RwLockReadGuard {
449             s: &self.s,
450             data: self.c.get(),
451             marker: marker::PhantomData,
452         })
453     }
454 
455     /// Attempts to acquire this `RwLock` with shared read access.
456     ///
457     /// If the access couldn't be acquired immediately, returns [`TryLockError`].
458     /// Otherwise, an RAII guard is returned which will release read access
459     /// when dropped.
460     ///
461     /// This method is identical to [`RwLock::try_read`], except that the
462     /// returned guard references the `RwLock` with an [`Arc`] rather than by
463     /// borrowing it. Therefore, the `RwLock` must be wrapped in an `Arc` to
464     /// call this method, and the guard will live for the `'static` lifetime,
465     /// as it keeps the `RwLock` alive by holding an `Arc`.
466     ///
467     /// [`TryLockError`]: TryLockError
468     ///
469     /// # Examples
470     ///
471     /// ```
472     /// use std::sync::Arc;
473     /// use tokio::sync::RwLock;
474     ///
475     /// #[tokio::main]
476     /// async fn main() {
477     ///     let lock = Arc::new(RwLock::new(1));
478     ///     let c_lock = lock.clone();
479     ///
480     ///     let v = lock.try_read_owned().unwrap();
481     ///     assert_eq!(*v, 1);
482     ///
483     ///     tokio::spawn(async move {
484     ///         // While main has an active read lock, we acquire one too.
485     ///         let n = c_lock.read_owned().await;
486     ///         assert_eq!(*n, 1);
487     ///     }).await.expect("The spawned task has panicked");
488     ///
489     ///     // Drop the guard when spawned task finishes.
490     ///     drop(v);
491     /// }
492     /// ```
try_read_owned(self: Arc<Self>) -> Result<OwnedRwLockReadGuard<T>, TryLockError>493     pub fn try_read_owned(self: Arc<Self>) -> Result<OwnedRwLockReadGuard<T>, TryLockError> {
494         match self.s.try_acquire(1) {
495             Ok(permit) => permit,
496             Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
497             Err(TryAcquireError::Closed) => unreachable!(),
498         }
499 
500         Ok(OwnedRwLockReadGuard {
501             data: self.c.get(),
502             lock: ManuallyDrop::new(self),
503             _p: PhantomData,
504         })
505     }
506 
507     /// Locks this `RwLock` with exclusive write access, causing the current
508     /// task to yield until the lock has been acquired.
509     ///
510     /// The calling task will yield while other writers or readers currently
511     /// have access to the lock.
512     ///
513     /// Returns an RAII guard which will drop the write access of this `RwLock`
514     /// when dropped.
515     ///
516     /// # Cancel safety
517     ///
518     /// This method uses a queue to fairly distribute locks in the order they
519     /// were requested. Cancelling a call to `write` makes you lose your place
520     /// in the queue.
521     ///
522     /// # Examples
523     ///
524     /// ```
525     /// use tokio::sync::RwLock;
526     ///
527     /// #[tokio::main]
528     /// async fn main() {
529     ///   let lock = RwLock::new(1);
530     ///
531     ///   let mut n = lock.write().await;
532     ///   *n = 2;
533     ///}
534     /// ```
write(&self) -> RwLockWriteGuard<'_, T>535     pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
536         self.s.acquire(self.mr).await.unwrap_or_else(|_| {
537             // The semaphore was closed. but, we never explicitly close it, and we have a
538             // handle to it through the Arc, which means that this can never happen.
539             unreachable!()
540         });
541         RwLockWriteGuard {
542             permits_acquired: self.mr,
543             s: &self.s,
544             data: self.c.get(),
545             marker: marker::PhantomData,
546         }
547     }
548 
549     /// Locks this `RwLock` with exclusive write access, causing the current
550     /// task to yield until the lock has been acquired.
551     ///
552     /// The calling task will yield while other writers or readers currently
553     /// have access to the lock.
554     ///
555     /// This method is identical to [`RwLock::write`], except that the returned
556     /// guard references the `RwLock` with an [`Arc`] rather than by borrowing
557     /// it. Therefore, the `RwLock` must be wrapped in an `Arc` to call this
558     /// method, and the guard will live for the `'static` lifetime, as it keeps
559     /// the `RwLock` alive by holding an `Arc`.
560     ///
561     /// Returns an RAII guard which will drop the write access of this `RwLock`
562     /// when dropped.
563     ///
564     /// # Cancel safety
565     ///
566     /// This method uses a queue to fairly distribute locks in the order they
567     /// were requested. Cancelling a call to `write_owned` makes you lose your
568     /// place in the queue.
569     ///
570     /// # Examples
571     ///
572     /// ```
573     /// use std::sync::Arc;
574     /// use tokio::sync::RwLock;
575     ///
576     /// #[tokio::main]
577     /// async fn main() {
578     ///   let lock = Arc::new(RwLock::new(1));
579     ///
580     ///   let mut n = lock.write_owned().await;
581     ///   *n = 2;
582     ///}
583     /// ```
write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T>584     pub async fn write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T> {
585         self.s.acquire(self.mr).await.unwrap_or_else(|_| {
586             // The semaphore was closed. but, we never explicitly close it, and we have a
587             // handle to it through the Arc, which means that this can never happen.
588             unreachable!()
589         });
590         OwnedRwLockWriteGuard {
591             permits_acquired: self.mr,
592             data: self.c.get(),
593             lock: ManuallyDrop::new(self),
594             _p: PhantomData,
595         }
596     }
597 
598     /// Attempts to acquire this `RwLock` with exclusive write access.
599     ///
600     /// If the access couldn't be acquired immediately, returns [`TryLockError`].
601     /// Otherwise, an RAII guard is returned which will release write access
602     /// when dropped.
603     ///
604     /// [`TryLockError`]: TryLockError
605     ///
606     /// # Examples
607     ///
608     /// ```
609     /// use tokio::sync::RwLock;
610     ///
611     /// #[tokio::main]
612     /// async fn main() {
613     ///     let rw = RwLock::new(1);
614     ///
615     ///     let v = rw.read().await;
616     ///     assert_eq!(*v, 1);
617     ///
618     ///     assert!(rw.try_write().is_err());
619     /// }
620     /// ```
try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError>621     pub fn try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError> {
622         match self.s.try_acquire(self.mr) {
623             Ok(permit) => permit,
624             Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
625             Err(TryAcquireError::Closed) => unreachable!(),
626         }
627 
628         Ok(RwLockWriteGuard {
629             permits_acquired: self.mr,
630             s: &self.s,
631             data: self.c.get(),
632             marker: marker::PhantomData,
633         })
634     }
635 
636     /// Attempts to acquire this `RwLock` with exclusive write access.
637     ///
638     /// If the access couldn't be acquired immediately, returns [`TryLockError`].
639     /// Otherwise, an RAII guard is returned which will release write access
640     /// when dropped.
641     ///
642     /// This method is identical to [`RwLock::try_write`], except that the
643     /// returned guard references the `RwLock` with an [`Arc`] rather than by
644     /// borrowing it. Therefore, the `RwLock` must be wrapped in an `Arc` to
645     /// call this method, and the guard will live for the `'static` lifetime,
646     /// as it keeps the `RwLock` alive by holding an `Arc`.
647     ///
648     /// [`TryLockError`]: TryLockError
649     ///
650     /// # Examples
651     ///
652     /// ```
653     /// use std::sync::Arc;
654     /// use tokio::sync::RwLock;
655     ///
656     /// #[tokio::main]
657     /// async fn main() {
658     ///     let rw = Arc::new(RwLock::new(1));
659     ///
660     ///     let v = Arc::clone(&rw).read_owned().await;
661     ///     assert_eq!(*v, 1);
662     ///
663     ///     assert!(rw.try_write_owned().is_err());
664     /// }
665     /// ```
try_write_owned(self: Arc<Self>) -> Result<OwnedRwLockWriteGuard<T>, TryLockError>666     pub fn try_write_owned(self: Arc<Self>) -> Result<OwnedRwLockWriteGuard<T>, TryLockError> {
667         match self.s.try_acquire(self.mr) {
668             Ok(permit) => permit,
669             Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
670             Err(TryAcquireError::Closed) => unreachable!(),
671         }
672 
673         Ok(OwnedRwLockWriteGuard {
674             permits_acquired: self.mr,
675             data: self.c.get(),
676             lock: ManuallyDrop::new(self),
677             _p: PhantomData,
678         })
679     }
680 
681     /// Returns a mutable reference to the underlying data.
682     ///
683     /// Since this call borrows the `RwLock` mutably, no actual locking needs to
684     /// take place -- the mutable borrow statically guarantees no locks exist.
685     ///
686     /// # Examples
687     ///
688     /// ```
689     /// use tokio::sync::RwLock;
690     ///
691     /// fn main() {
692     ///     let mut lock = RwLock::new(1);
693     ///
694     ///     let n = lock.get_mut();
695     ///     *n = 2;
696     /// }
697     /// ```
get_mut(&mut self) -> &mut T698     pub fn get_mut(&mut self) -> &mut T {
699         unsafe {
700             // Safety: This is https://github.com/rust-lang/rust/pull/76936
701             &mut *self.c.get()
702         }
703     }
704 
705     /// Consumes the lock, returning the underlying data.
into_inner(self) -> T where T: Sized,706     pub fn into_inner(self) -> T
707     where
708         T: Sized,
709     {
710         self.c.into_inner()
711     }
712 }
713 
714 impl<T> From<T> for RwLock<T> {
from(s: T) -> Self715     fn from(s: T) -> Self {
716         Self::new(s)
717     }
718 }
719 
720 impl<T: ?Sized> Default for RwLock<T>
721 where
722     T: Default,
723 {
default() -> Self724     fn default() -> Self {
725         Self::new(T::default())
726     }
727 }
728