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 /// # Examples
303 ///
304 /// ```
305 /// use std::sync::Arc;
306 /// use tokio::sync::RwLock;
307 ///
308 /// #[tokio::main]
309 /// async fn main() {
310 /// let lock = Arc::new(RwLock::new(1));
311 /// let c_lock = lock.clone();
312 ///
313 /// let n = lock.read().await;
314 /// assert_eq!(*n, 1);
315 ///
316 /// tokio::spawn(async move {
317 /// // While main has an active read lock, we acquire one too.
318 /// let r = c_lock.read().await;
319 /// assert_eq!(*r, 1);
320 /// }).await.expect("The spawned task has panicked");
321 ///
322 /// // Drop the guard after the spawned task finishes.
323 /// drop(n);
324 ///}
325 /// ```
read(&self) -> RwLockReadGuard<'_, T>326 pub async fn read(&self) -> RwLockReadGuard<'_, T> {
327 self.s.acquire(1).await.unwrap_or_else(|_| {
328 // The semaphore was closed. but, we never explicitly close it, and we have a
329 // handle to it through the Arc, which means that this can never happen.
330 unreachable!()
331 });
332 RwLockReadGuard {
333 s: &self.s,
334 data: self.c.get(),
335 marker: marker::PhantomData,
336 }
337 }
338
339 /// Locks this `RwLock` with shared read access, causing the current task
340 /// to yield until the lock has been acquired.
341 ///
342 /// The calling task will yield until there are no writers which hold the
343 /// lock. There may be other readers inside the lock when the task resumes.
344 ///
345 /// This method is identical to [`RwLock::read`], except that the returned
346 /// guard references the `RwLock` with an [`Arc`] rather than by borrowing
347 /// it. Therefore, the `RwLock` must be wrapped in an `Arc` to call this
348 /// method, and the guard will live for the `'static` lifetime, as it keeps
349 /// the `RwLock` alive by holding an `Arc`.
350 ///
351 /// Note that under the priority policy of [`RwLock`], read locks are not
352 /// granted until prior write locks, to prevent starvation. Therefore
353 /// deadlock may occur if a read lock is held by the current task, a write
354 /// lock attempt is made, and then a subsequent read lock attempt is made
355 /// by the current task.
356 ///
357 /// Returns an RAII guard which will drop this read access of the `RwLock`
358 /// when dropped.
359 ///
360 /// # Examples
361 ///
362 /// ```
363 /// use std::sync::Arc;
364 /// use tokio::sync::RwLock;
365 ///
366 /// #[tokio::main]
367 /// async fn main() {
368 /// let lock = Arc::new(RwLock::new(1));
369 /// let c_lock = lock.clone();
370 ///
371 /// let n = lock.read_owned().await;
372 /// assert_eq!(*n, 1);
373 ///
374 /// tokio::spawn(async move {
375 /// // While main has an active read lock, we acquire one too.
376 /// let r = c_lock.read_owned().await;
377 /// assert_eq!(*r, 1);
378 /// }).await.expect("The spawned task has panicked");
379 ///
380 /// // Drop the guard after the spawned task finishes.
381 /// drop(n);
382 ///}
383 /// ```
read_owned(self: Arc<Self>) -> OwnedRwLockReadGuard<T>384 pub async fn read_owned(self: Arc<Self>) -> OwnedRwLockReadGuard<T> {
385 self.s.acquire(1).await.unwrap_or_else(|_| {
386 // The semaphore was closed. but, we never explicitly close it, and we have a
387 // handle to it through the Arc, which means that this can never happen.
388 unreachable!()
389 });
390 OwnedRwLockReadGuard {
391 data: self.c.get(),
392 lock: ManuallyDrop::new(self),
393 _p: PhantomData,
394 }
395 }
396
397 /// Attempts to acquire this `RwLock` with shared read access.
398 ///
399 /// If the access couldn't be acquired immediately, returns [`TryLockError`].
400 /// Otherwise, an RAII guard is returned which will release read access
401 /// when dropped.
402 ///
403 /// [`TryLockError`]: TryLockError
404 ///
405 /// # Examples
406 ///
407 /// ```
408 /// use std::sync::Arc;
409 /// use tokio::sync::RwLock;
410 ///
411 /// #[tokio::main]
412 /// async fn main() {
413 /// let lock = Arc::new(RwLock::new(1));
414 /// let c_lock = lock.clone();
415 ///
416 /// let v = lock.try_read().unwrap();
417 /// assert_eq!(*v, 1);
418 ///
419 /// tokio::spawn(async move {
420 /// // While main has an active read lock, we acquire one too.
421 /// let n = c_lock.read().await;
422 /// assert_eq!(*n, 1);
423 /// }).await.expect("The spawned task has panicked");
424 ///
425 /// // Drop the guard when spawned task finishes.
426 /// drop(v);
427 /// }
428 /// ```
try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError>429 pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError> {
430 match self.s.try_acquire(1) {
431 Ok(permit) => permit,
432 Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
433 Err(TryAcquireError::Closed) => unreachable!(),
434 }
435
436 Ok(RwLockReadGuard {
437 s: &self.s,
438 data: self.c.get(),
439 marker: marker::PhantomData,
440 })
441 }
442
443 /// Attempts to acquire this `RwLock` with shared read access.
444 ///
445 /// If the access couldn't be acquired immediately, returns [`TryLockError`].
446 /// Otherwise, an RAII guard is returned which will release read access
447 /// when dropped.
448 ///
449 /// This method is identical to [`RwLock::try_read`], except that the
450 /// returned guard references the `RwLock` with an [`Arc`] rather than by
451 /// borrowing it. Therefore, the `RwLock` must be wrapped in an `Arc` to
452 /// call this method, and the guard will live for the `'static` lifetime,
453 /// as it keeps the `RwLock` alive by holding an `Arc`.
454 ///
455 /// [`TryLockError`]: TryLockError
456 ///
457 /// # Examples
458 ///
459 /// ```
460 /// use std::sync::Arc;
461 /// use tokio::sync::RwLock;
462 ///
463 /// #[tokio::main]
464 /// async fn main() {
465 /// let lock = Arc::new(RwLock::new(1));
466 /// let c_lock = lock.clone();
467 ///
468 /// let v = lock.try_read_owned().unwrap();
469 /// assert_eq!(*v, 1);
470 ///
471 /// tokio::spawn(async move {
472 /// // While main has an active read lock, we acquire one too.
473 /// let n = c_lock.read_owned().await;
474 /// assert_eq!(*n, 1);
475 /// }).await.expect("The spawned task has panicked");
476 ///
477 /// // Drop the guard when spawned task finishes.
478 /// drop(v);
479 /// }
480 /// ```
try_read_owned(self: Arc<Self>) -> Result<OwnedRwLockReadGuard<T>, TryLockError>481 pub fn try_read_owned(self: Arc<Self>) -> Result<OwnedRwLockReadGuard<T>, TryLockError> {
482 match self.s.try_acquire(1) {
483 Ok(permit) => permit,
484 Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
485 Err(TryAcquireError::Closed) => unreachable!(),
486 }
487
488 Ok(OwnedRwLockReadGuard {
489 data: self.c.get(),
490 lock: ManuallyDrop::new(self),
491 _p: PhantomData,
492 })
493 }
494
495 /// Locks this `RwLock` with exclusive write access, causing the current
496 /// task to yield until the lock has been acquired.
497 ///
498 /// The calling task will yield while other writers or readers currently
499 /// have access to the lock.
500 ///
501 /// Returns an RAII guard which will drop the write access of this `RwLock`
502 /// when dropped.
503 ///
504 /// # Examples
505 ///
506 /// ```
507 /// use tokio::sync::RwLock;
508 ///
509 /// #[tokio::main]
510 /// async fn main() {
511 /// let lock = RwLock::new(1);
512 ///
513 /// let mut n = lock.write().await;
514 /// *n = 2;
515 ///}
516 /// ```
write(&self) -> RwLockWriteGuard<'_, T>517 pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
518 self.s.acquire(self.mr).await.unwrap_or_else(|_| {
519 // The semaphore was closed. but, we never explicitly close it, and we have a
520 // handle to it through the Arc, which means that this can never happen.
521 unreachable!()
522 });
523 RwLockWriteGuard {
524 permits_acquired: self.mr,
525 s: &self.s,
526 data: self.c.get(),
527 marker: marker::PhantomData,
528 }
529 }
530
531 /// Locks this `RwLock` with exclusive write access, causing the current
532 /// task to yield until the lock has been acquired.
533 ///
534 /// The calling task will yield while other writers or readers currently
535 /// have access to the lock.
536 ///
537 /// This method is identical to [`RwLock::write`], except that the returned
538 /// guard references the `RwLock` with an [`Arc`] rather than by borrowing
539 /// it. Therefore, the `RwLock` must be wrapped in an `Arc` to call this
540 /// method, and the guard will live for the `'static` lifetime, as it keeps
541 /// the `RwLock` alive by holding an `Arc`.
542 ///
543 /// Returns an RAII guard which will drop the write access of this `RwLock`
544 /// when dropped.
545 ///
546 /// # Examples
547 ///
548 /// ```
549 /// use std::sync::Arc;
550 /// use tokio::sync::RwLock;
551 ///
552 /// #[tokio::main]
553 /// async fn main() {
554 /// let lock = Arc::new(RwLock::new(1));
555 ///
556 /// let mut n = lock.write_owned().await;
557 /// *n = 2;
558 ///}
559 /// ```
write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T>560 pub async fn write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T> {
561 self.s.acquire(self.mr).await.unwrap_or_else(|_| {
562 // The semaphore was closed. but, we never explicitly close it, and we have a
563 // handle to it through the Arc, which means that this can never happen.
564 unreachable!()
565 });
566 OwnedRwLockWriteGuard {
567 permits_acquired: self.mr,
568 data: self.c.get(),
569 lock: ManuallyDrop::new(self),
570 _p: PhantomData,
571 }
572 }
573
574 /// Attempts to acquire this `RwLock` with exclusive write access.
575 ///
576 /// If the access couldn't be acquired immediately, returns [`TryLockError`].
577 /// Otherwise, an RAII guard is returned which will release write access
578 /// when dropped.
579 ///
580 /// [`TryLockError`]: TryLockError
581 ///
582 /// # Examples
583 ///
584 /// ```
585 /// use tokio::sync::RwLock;
586 ///
587 /// #[tokio::main]
588 /// async fn main() {
589 /// let rw = RwLock::new(1);
590 ///
591 /// let v = rw.read().await;
592 /// assert_eq!(*v, 1);
593 ///
594 /// assert!(rw.try_write().is_err());
595 /// }
596 /// ```
try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError>597 pub fn try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError> {
598 match self.s.try_acquire(self.mr) {
599 Ok(permit) => permit,
600 Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
601 Err(TryAcquireError::Closed) => unreachable!(),
602 }
603
604 Ok(RwLockWriteGuard {
605 permits_acquired: self.mr,
606 s: &self.s,
607 data: self.c.get(),
608 marker: marker::PhantomData,
609 })
610 }
611
612 /// Attempts to acquire this `RwLock` with exclusive write access.
613 ///
614 /// If the access couldn't be acquired immediately, returns [`TryLockError`].
615 /// Otherwise, an RAII guard is returned which will release write access
616 /// when dropped.
617 ///
618 /// This method is identical to [`RwLock::try_write`], except that the
619 /// returned guard references the `RwLock` with an [`Arc`] rather than by
620 /// borrowing it. Therefore, the `RwLock` must be wrapped in an `Arc` to
621 /// call this method, and the guard will live for the `'static` lifetime,
622 /// as it keeps the `RwLock` alive by holding an `Arc`.
623 ///
624 /// [`TryLockError`]: TryLockError
625 ///
626 /// # Examples
627 ///
628 /// ```
629 /// use std::sync::Arc;
630 /// use tokio::sync::RwLock;
631 ///
632 /// #[tokio::main]
633 /// async fn main() {
634 /// let rw = Arc::new(RwLock::new(1));
635 ///
636 /// let v = Arc::clone(&rw).read_owned().await;
637 /// assert_eq!(*v, 1);
638 ///
639 /// assert!(rw.try_write_owned().is_err());
640 /// }
641 /// ```
try_write_owned(self: Arc<Self>) -> Result<OwnedRwLockWriteGuard<T>, TryLockError>642 pub fn try_write_owned(self: Arc<Self>) -> Result<OwnedRwLockWriteGuard<T>, TryLockError> {
643 match self.s.try_acquire(self.mr) {
644 Ok(permit) => permit,
645 Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
646 Err(TryAcquireError::Closed) => unreachable!(),
647 }
648
649 Ok(OwnedRwLockWriteGuard {
650 permits_acquired: self.mr,
651 data: self.c.get(),
652 lock: ManuallyDrop::new(self),
653 _p: PhantomData,
654 })
655 }
656
657 /// Returns a mutable reference to the underlying data.
658 ///
659 /// Since this call borrows the `RwLock` mutably, no actual locking needs to
660 /// take place -- the mutable borrow statically guarantees no locks exist.
661 ///
662 /// # Examples
663 ///
664 /// ```
665 /// use tokio::sync::RwLock;
666 ///
667 /// fn main() {
668 /// let mut lock = RwLock::new(1);
669 ///
670 /// let n = lock.get_mut();
671 /// *n = 2;
672 /// }
673 /// ```
get_mut(&mut self) -> &mut T674 pub fn get_mut(&mut self) -> &mut T {
675 unsafe {
676 // Safety: This is https://github.com/rust-lang/rust/pull/76936
677 &mut *self.c.get()
678 }
679 }
680
681 /// Consumes the lock, returning the underlying data.
into_inner(self) -> T where T: Sized,682 pub fn into_inner(self) -> T
683 where
684 T: Sized,
685 {
686 self.c.into_inner()
687 }
688 }
689
690 impl<T> From<T> for RwLock<T> {
from(s: T) -> Self691 fn from(s: T) -> Self {
692 Self::new(s)
693 }
694 }
695
696 impl<T: ?Sized> Default for RwLock<T>
697 where
698 T: Default,
699 {
default() -> Self700 fn default() -> Self {
701 Self::new(T::default())
702 }
703 }
704