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