std/sync/nonpoison/rwlock.rs
1use crate::cell::UnsafeCell;
2use crate::fmt;
3use crate::marker::PhantomData;
4use crate::mem::{self, ManuallyDrop, forget};
5use crate::ops::{Deref, DerefMut};
6use crate::ptr::NonNull;
7use crate::sync::nonpoison::{TryLockResult, WouldBlock};
8use crate::sys::sync as sys;
9
10/// A reader-writer lock that does not keep track of lock poisoning.
11///
12/// For more information about reader-writer locks, check out the documentation for the poisoning
13/// variant of this lock (which can be found at [`poison::RwLock`]).
14///
15/// [`poison::RwLock`]: crate::sync::poison::RwLock
16///
17/// # Examples
18///
19/// ```
20/// #![feature(nonpoison_rwlock)]
21///
22/// use std::sync::nonpoison::RwLock;
23///
24/// let lock = RwLock::new(5);
25///
26/// // many reader locks can be held at once
27/// {
28/// let r1 = lock.read();
29/// let r2 = lock.read();
30/// assert_eq!(*r1, 5);
31/// assert_eq!(*r2, 5);
32/// } // read locks are dropped at this point
33///
34/// // only one write lock may be held, however
35/// {
36/// let mut w = lock.write();
37/// *w += 1;
38/// assert_eq!(*w, 6);
39/// } // write lock is dropped here
40/// ```
41#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
42#[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonRwLock")]
43pub struct RwLock<T: ?Sized> {
44 /// The inner [`sys::RwLock`] that synchronizes thread access to the protected data.
45 inner: sys::RwLock,
46 /// The lock-protected data.
47 data: UnsafeCell<T>,
48}
49
50#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
51unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
52
53#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
54unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
55
56////////////////////////////////////////////////////////////////////////////////////////////////////
57// Guards
58////////////////////////////////////////////////////////////////////////////////////////////////////
59
60/// RAII structure used to release the shared read access of a lock when
61/// dropped.
62///
63/// This structure is created by the [`read`] and [`try_read`] methods on
64/// [`RwLock`].
65///
66/// [`read`]: RwLock::read
67/// [`try_read`]: RwLock::try_read
68#[must_use = "if unused the RwLock will immediately unlock"]
69#[must_not_suspend = "holding a RwLockReadGuard across suspend \
70 points can cause deadlocks, delays, \
71 and cause Futures to not implement `Send`"]
72#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
73#[clippy::has_significant_drop]
74#[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonRwLockReadGuard")]
75pub struct RwLockReadGuard<'rwlock, T: ?Sized + 'rwlock> {
76 /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of
77 /// `&'rwlock T` to avoid `noalias` violations, because a `RwLockReadGuard` instance only holds
78 /// immutability until it drops, not for its whole scope.
79 /// `NonNull` is preferable over `*const T` to allow for niche optimizations. `NonNull` is also
80 /// covariant over `T`, just like we would have with `&T`.
81 data: NonNull<T>,
82 /// A reference to the internal [`sys::RwLock`] that we have read-locked.
83 inner_lock: &'rwlock sys::RwLock,
84}
85
86#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
87impl<T: ?Sized> !Send for RwLockReadGuard<'_, T> {}
88
89#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
90unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {}
91
92/// RAII structure used to release the exclusive write access of a lock when
93/// dropped.
94///
95/// This structure is created by the [`write`] and [`try_write`] methods
96/// on [`RwLock`].
97///
98/// [`write`]: RwLock::write
99/// [`try_write`]: RwLock::try_write
100#[must_use = "if unused the RwLock will immediately unlock"]
101#[must_not_suspend = "holding a RwLockWriteGuard across suspend \
102 points can cause deadlocks, delays, \
103 and cause Future's to not implement `Send`"]
104#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
105#[clippy::has_significant_drop]
106#[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonRwLockWriteGuard")]
107pub struct RwLockWriteGuard<'rwlock, T: ?Sized + 'rwlock> {
108 /// A reference to the [`RwLock`] that we have write-locked.
109 lock: &'rwlock RwLock<T>,
110}
111
112#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
113impl<T: ?Sized> !Send for RwLockWriteGuard<'_, T> {}
114
115#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
116unsafe impl<T: ?Sized + Sync> Sync for RwLockWriteGuard<'_, T> {}
117
118/// RAII structure used to release the shared read access of a lock when
119/// dropped, which can point to a subfield of the protected data.
120///
121/// This structure is created by the [`map`] and [`filter_map`] methods
122/// on [`RwLockReadGuard`].
123///
124/// [`map`]: RwLockReadGuard::map
125/// [`filter_map`]: RwLockReadGuard::filter_map
126#[must_use = "if unused the RwLock will immediately unlock"]
127#[must_not_suspend = "holding a MappedRwLockReadGuard across suspend \
128 points can cause deadlocks, delays, \
129 and cause Futures to not implement `Send`"]
130#[unstable(feature = "mapped_lock_guards", issue = "117108")]
131// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
132#[clippy::has_significant_drop]
133pub struct MappedRwLockReadGuard<'rwlock, T: ?Sized + 'rwlock> {
134 /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of
135 /// `&'rwlock T` to avoid `noalias` violations, because a `MappedRwLockReadGuard` instance only
136 /// holds immutability until it drops, not for its whole scope.
137 /// `NonNull` is preferable over `*const T` to allow for niche optimizations. `NonNull` is also
138 /// covariant over `T`, just like we would have with `&T`.
139 data: NonNull<T>,
140 /// A reference to the internal [`sys::RwLock`] that we have read-locked.
141 inner_lock: &'rwlock sys::RwLock,
142}
143
144#[unstable(feature = "mapped_lock_guards", issue = "117108")]
145// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
146impl<T: ?Sized> !Send for MappedRwLockReadGuard<'_, T> {}
147
148#[unstable(feature = "mapped_lock_guards", issue = "117108")]
149// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
150unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockReadGuard<'_, T> {}
151
152/// RAII structure used to release the exclusive write access of a lock when
153/// dropped, which can point to a subfield of the protected data.
154///
155/// This structure is created by the [`map`] and [`filter_map`] methods
156/// on [`RwLockWriteGuard`].
157///
158/// [`map`]: RwLockWriteGuard::map
159/// [`filter_map`]: RwLockWriteGuard::filter_map
160#[must_use = "if unused the RwLock will immediately unlock"]
161#[must_not_suspend = "holding a MappedRwLockWriteGuard across suspend \
162 points can cause deadlocks, delays, \
163 and cause Future's to not implement `Send`"]
164#[unstable(feature = "mapped_lock_guards", issue = "117108")]
165// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
166#[clippy::has_significant_drop]
167pub struct MappedRwLockWriteGuard<'rwlock, T: ?Sized + 'rwlock> {
168 /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of
169 /// `&'rwlock T` to avoid `noalias` violations, because a `MappedRwLockWriteGuard` instance only
170 /// holds uniquneness until it drops, not for its whole scope.
171 /// `NonNull` is preferable over `*const T` to allow for niche optimizations.
172 data: NonNull<T>,
173 /// `NonNull` is covariant over `T`, so we add a `PhantomData<&'rwlock mut T>` field here to
174 /// enforce the correct invariance over `T`.
175 _variance: PhantomData<&'rwlock mut T>,
176 /// A reference to the internal [`sys::RwLock`] that we have write-locked.
177 inner_lock: &'rwlock sys::RwLock,
178}
179
180#[unstable(feature = "mapped_lock_guards", issue = "117108")]
181// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
182impl<T: ?Sized> !Send for MappedRwLockWriteGuard<'_, T> {}
183
184#[unstable(feature = "mapped_lock_guards", issue = "117108")]
185// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
186unsafe impl<T: ?Sized + Sync> Sync for MappedRwLockWriteGuard<'_, T> {}
187
188////////////////////////////////////////////////////////////////////////////////////////////////////
189// Implementations
190////////////////////////////////////////////////////////////////////////////////////////////////////
191
192impl<T> RwLock<T> {
193 /// Creates a new instance of an `RwLock<T>` which is unlocked.
194 ///
195 /// # Examples
196 ///
197 /// ```
198 /// #![feature(nonpoison_rwlock)]
199 ///
200 /// use std::sync::nonpoison::RwLock;
201 ///
202 /// let lock = RwLock::new(5);
203 /// ```
204 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
205 #[inline]
206 pub const fn new(t: T) -> RwLock<T> {
207 RwLock { inner: sys::RwLock::new(), data: UnsafeCell::new(t) }
208 }
209
210 /// Returns the contained value by cloning it.
211 ///
212 /// # Examples
213 ///
214 /// ```
215 /// #![feature(nonpoison_rwlock)]
216 /// #![feature(lock_value_accessors)]
217 ///
218 /// use std::sync::nonpoison::RwLock;
219 ///
220 /// let mut lock = RwLock::new(7);
221 ///
222 /// assert_eq!(lock.get_cloned(), 7);
223 /// ```
224 #[unstable(feature = "lock_value_accessors", issue = "133407")]
225 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
226 pub fn get_cloned(&self) -> T
227 where
228 T: Clone,
229 {
230 self.read().clone()
231 }
232
233 /// Sets the contained value.
234 ///
235 /// # Examples
236 ///
237 /// ```
238 /// #![feature(nonpoison_rwlock)]
239 /// #![feature(lock_value_accessors)]
240 ///
241 /// use std::sync::nonpoison::RwLock;
242 ///
243 /// let mut lock = RwLock::new(7);
244 ///
245 /// assert_eq!(lock.get_cloned(), 7);
246 /// lock.set(11);
247 /// assert_eq!(lock.get_cloned(), 11);
248 /// ```
249 #[unstable(feature = "lock_value_accessors", issue = "133407")]
250 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
251 pub fn set(&self, value: T) {
252 if mem::needs_drop::<T>() {
253 // If the contained value has a non-trivial destructor, we
254 // call that destructor after the lock has been released.
255 drop(self.replace(value))
256 } else {
257 *self.write() = value;
258 }
259 }
260
261 /// Replaces the contained value with `value`, and returns the old contained value.
262 ///
263 /// # Examples
264 ///
265 /// ```
266 /// #![feature(nonpoison_rwlock)]
267 /// #![feature(lock_value_accessors)]
268 ///
269 /// use std::sync::nonpoison::RwLock;
270 ///
271 /// let mut lock = RwLock::new(7);
272 ///
273 /// assert_eq!(lock.replace(11), 7);
274 /// assert_eq!(lock.get_cloned(), 11);
275 /// ```
276 #[unstable(feature = "lock_value_accessors", issue = "133407")]
277 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
278 pub fn replace(&self, value: T) -> T {
279 let mut guard = self.write();
280 mem::replace(&mut *guard, value)
281 }
282}
283
284impl<T: ?Sized> RwLock<T> {
285 /// Locks this `RwLock` with shared read access, blocking the current thread
286 /// until it can be acquired.
287 ///
288 /// The calling thread will be blocked until there are no more writers which
289 /// hold the lock. There may be other readers currently inside the lock when
290 /// this method returns. This method does not provide any guarantees with
291 /// respect to the ordering of whether contentious readers or writers will
292 /// acquire the lock first.
293 ///
294 /// Returns an RAII guard which will release this thread's shared access
295 /// once it is dropped.
296 ///
297 /// # Panics
298 ///
299 /// This function might panic when called if the lock is already held by the current thread.
300 ///
301 /// # Examples
302 ///
303 /// ```
304 /// #![feature(nonpoison_rwlock)]
305 ///
306 /// use std::sync::Arc;
307 /// use std::sync::nonpoison::RwLock;
308 /// use std::thread;
309 ///
310 /// let lock = Arc::new(RwLock::new(1));
311 /// let c_lock = Arc::clone(&lock);
312 ///
313 /// let n = lock.read();
314 /// assert_eq!(*n, 1);
315 ///
316 /// thread::spawn(move || {
317 /// let r = c_lock.read();
318 /// }).join().unwrap();
319 /// ```
320 #[inline]
321 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
322 pub fn read(&self) -> RwLockReadGuard<'_, T> {
323 unsafe {
324 self.inner.read();
325 RwLockReadGuard::new(self)
326 }
327 }
328
329 /// Attempts to acquire this `RwLock` with shared read access.
330 ///
331 /// If the access could not be granted at this time, then `Err` is returned.
332 /// Otherwise, an RAII guard is returned which will release the shared access
333 /// when it is dropped.
334 ///
335 /// This function does not block.
336 ///
337 /// This function does not provide any guarantees with respect to the ordering
338 /// of whether contentious readers or writers will acquire the lock first.
339 ///
340 /// # Errors
341 ///
342 /// This function will return the [`WouldBlock`] error if the `RwLock` could
343 /// not be acquired because it was already locked exclusively.
344 ///
345 /// # Examples
346 ///
347 /// ```
348 /// #![feature(nonpoison_rwlock)]
349 ///
350 /// use std::sync::nonpoison::RwLock;
351 ///
352 /// let lock = RwLock::new(1);
353 ///
354 /// match lock.try_read() {
355 /// Ok(n) => assert_eq!(*n, 1),
356 /// Err(_) => unreachable!(),
357 /// };
358 /// ```
359 #[inline]
360 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
361 pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> {
362 unsafe {
363 if self.inner.try_read() { Ok(RwLockReadGuard::new(self)) } else { Err(WouldBlock) }
364 }
365 }
366
367 /// Locks this `RwLock` with exclusive write access, blocking the current
368 /// thread until it can be acquired.
369 ///
370 /// This function will not return while other writers or other readers
371 /// currently have access to the lock.
372 ///
373 /// Returns an RAII guard which will drop the write access of this `RwLock`
374 /// when dropped.
375 ///
376 /// # Panics
377 ///
378 /// This function might panic when called if the lock is already held by the current thread.
379 ///
380 /// # Examples
381 ///
382 /// ```
383 /// #![feature(nonpoison_rwlock)]
384 ///
385 /// use std::sync::nonpoison::RwLock;
386 ///
387 /// let lock = RwLock::new(1);
388 ///
389 /// let mut n = lock.write();
390 /// *n = 2;
391 ///
392 /// assert!(lock.try_read().is_err());
393 /// ```
394 #[inline]
395 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
396 pub fn write(&self) -> RwLockWriteGuard<'_, T> {
397 unsafe {
398 self.inner.write();
399 RwLockWriteGuard::new(self)
400 }
401 }
402
403 /// Attempts to lock this `RwLock` with exclusive write access.
404 ///
405 /// If the lock could not be acquired at this time, then `Err` is returned.
406 /// Otherwise, an RAII guard is returned which will release the lock when
407 /// it is dropped.
408 ///
409 /// This function does not block.
410 ///
411 /// This function does not provide any guarantees with respect to the ordering
412 /// of whether contentious readers or writers will acquire the lock first.
413 ///
414 /// # Errors
415 ///
416 /// This function will return the [`WouldBlock`] error if the `RwLock` could
417 /// not be acquired because it was already locked.
418 ///
419 /// [`WouldBlock`]: WouldBlock
420 ///
421 /// # Examples
422 ///
423 /// ```
424 /// #![feature(nonpoison_rwlock)]
425 ///
426 /// use std::sync::nonpoison::RwLock;
427 ///
428 /// let lock = RwLock::new(1);
429 ///
430 /// let n = lock.read();
431 /// assert_eq!(*n, 1);
432 ///
433 /// assert!(lock.try_write().is_err());
434 /// ```
435 #[inline]
436 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
437 pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
438 unsafe {
439 if self.inner.try_write() { Ok(RwLockWriteGuard::new(self)) } else { Err(WouldBlock) }
440 }
441 }
442
443 /// Consumes this `RwLock`, returning the underlying data.
444 ///
445 /// # Examples
446 ///
447 /// ```
448 /// #![feature(nonpoison_rwlock)]
449 ///
450 /// use std::sync::nonpoison::RwLock;
451 ///
452 /// let lock = RwLock::new(String::new());
453 /// {
454 /// let mut s = lock.write();
455 /// *s = "modified".to_owned();
456 /// }
457 /// assert_eq!(lock.into_inner(), "modified");
458 /// ```
459 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
460 pub fn into_inner(self) -> T
461 where
462 T: Sized,
463 {
464 self.data.into_inner()
465 }
466
467 /// Returns a mutable reference to the underlying data.
468 ///
469 /// Since this call borrows the `RwLock` mutably, no actual locking needs to
470 /// take place -- the mutable borrow statically guarantees no new locks can be acquired
471 /// while this reference exists. Note that this method does not clear any previously abandoned
472 /// locks (e.g., via [`forget()`] on a [`RwLockReadGuard`] or [`RwLockWriteGuard`]).
473 ///
474 /// # Examples
475 ///
476 /// ```
477 /// #![feature(nonpoison_rwlock)]
478 ///
479 /// use std::sync::nonpoison::RwLock;
480 ///
481 /// let mut lock = RwLock::new(0);
482 /// *lock.get_mut() = 10;
483 /// assert_eq!(*lock.read(), 10);
484 /// ```
485 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
486 pub fn get_mut(&mut self) -> &mut T {
487 self.data.get_mut()
488 }
489
490 /// Returns a raw pointer to the underlying data.
491 ///
492 /// The returned pointer is always non-null and properly aligned, but it is
493 /// the user's responsibility to ensure that any reads and writes through it
494 /// are properly synchronized to avoid data races, and that it is not read
495 /// or written through after the lock is dropped.
496 #[unstable(feature = "rwlock_data_ptr", issue = "140368")]
497 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
498 pub const fn data_ptr(&self) -> *mut T {
499 self.data.get()
500 }
501
502 /// Locks this `RwLock` with shared read access to the underlying data by passing
503 /// a reference to the given closure.
504 ///
505 /// This method acquires the lock, calls the provided closure with a reference
506 /// to the data, and returns the result of the closure. The lock is released after
507 /// the closure completes, even if it panics.
508 ///
509 /// # Examples
510 ///
511 /// ```
512 /// #![feature(lock_value_accessors, nonpoison_rwlock)]
513 ///
514 /// use std::sync::nonpoison::RwLock;
515 ///
516 /// let rwlock = RwLock::new(2);
517 /// let result = rwlock.with(|data| *data + 3);
518 ///
519 /// assert_eq!(result, 5);
520 /// ```
521 #[unstable(feature = "lock_value_accessors", issue = "133407")]
522 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
523 pub fn with<F, R>(&self, f: F) -> R
524 where
525 F: FnOnce(&T) -> R,
526 {
527 f(&self.read())
528 }
529
530 /// Locks this `RwLock` with exclusive write access to the underlying data by passing
531 /// a mutable reference to the given closure.
532 ///
533 /// This method acquires the lock, calls the provided closure with a mutable reference
534 /// to the data, and returns the result of the closure. The lock is released after
535 /// the closure completes, even if it panics.
536 ///
537 /// # Examples
538 ///
539 /// ```
540 /// #![feature(lock_value_accessors, nonpoison_rwlock)]
541 ///
542 /// use std::sync::nonpoison::RwLock;
543 ///
544 /// let rwlock = RwLock::new(2);
545 ///
546 /// let result = rwlock.with_mut(|data| {
547 /// *data += 3;
548 ///
549 /// *data + 5
550 /// });
551 ///
552 /// assert_eq!(*rwlock.read(), 5);
553 /// assert_eq!(result, 10);
554 /// ```
555 #[unstable(feature = "lock_value_accessors", issue = "133407")]
556 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
557 pub fn with_mut<F, R>(&self, f: F) -> R
558 where
559 F: FnOnce(&mut T) -> R,
560 {
561 f(&mut self.write())
562 }
563}
564
565#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
566impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
567 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568 let mut d = f.debug_struct("RwLock");
569 match self.try_read() {
570 Ok(guard) => {
571 d.field("data", &&*guard);
572 }
573 Err(WouldBlock) => {
574 d.field("data", &format_args!("<locked>"));
575 }
576 }
577 d.finish_non_exhaustive()
578 }
579}
580
581#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
582impl<T: Default> Default for RwLock<T> {
583 /// Creates a new `RwLock<T>`, with the `Default` value for T.
584 fn default() -> RwLock<T> {
585 RwLock::new(Default::default())
586 }
587}
588
589#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
590impl<T> From<T> for RwLock<T> {
591 /// Creates a new instance of an `RwLock<T>` which is unlocked.
592 /// This is equivalent to [`RwLock::new`].
593 fn from(t: T) -> Self {
594 RwLock::new(t)
595 }
596}
597
598impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
599 /// Creates a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
600 ///
601 /// # Safety
602 ///
603 /// This function is safe if and only if the same thread has successfully and safely called
604 /// `lock.inner.read()`, `lock.inner.try_read()`, or `lock.inner.downgrade()` before
605 /// instantiating this object.
606 unsafe fn new(lock: &'rwlock RwLock<T>) -> RwLockReadGuard<'rwlock, T> {
607 RwLockReadGuard {
608 data: unsafe { NonNull::new_unchecked(lock.data.get()) },
609 inner_lock: &lock.inner,
610 }
611 }
612
613 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data, e.g.
614 /// an enum variant.
615 ///
616 /// The `RwLock` is already locked for reading, so this cannot fail.
617 ///
618 /// This is an associated function that needs to be used as
619 /// `RwLockReadGuard::map(...)`. A method would interfere with methods of
620 /// the same name on the contents of the `RwLockReadGuard` used through
621 /// `Deref`.
622 ///
623 /// # Panics
624 ///
625 /// If the closure panics, the guard will be dropped (unlocked).
626 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
627 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
628 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
629 where
630 F: FnOnce(&T) -> &U,
631 U: ?Sized,
632 {
633 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
634 // was created, and have been upheld throughout `map` and/or `filter_map`.
635 // The signature of the closure guarantees that it will not "leak" the lifetime of the
636 // reference passed to it. If the closure panics, the guard will be dropped.
637 let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
638 let orig = ManuallyDrop::new(orig);
639 MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
640 }
641
642 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The
643 /// original guard is returned as an `Err(...)` if the closure returns
644 /// `None`.
645 ///
646 /// The `RwLock` is already locked for reading, so this cannot fail.
647 ///
648 /// This is an associated function that needs to be used as
649 /// `RwLockReadGuard::filter_map(...)`. A method would interfere with methods
650 /// of the same name on the contents of the `RwLockReadGuard` used through
651 /// `Deref`.
652 ///
653 /// # Panics
654 ///
655 /// If the closure panics, the guard will be dropped (unlocked).
656 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
657 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
658 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
659 where
660 F: FnOnce(&T) -> Option<&U>,
661 U: ?Sized,
662 {
663 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
664 // was created, and have been upheld throughout `map` and/or `filter_map`.
665 // The signature of the closure guarantees that it will not "leak" the lifetime of the
666 // reference passed to it. If the closure panics, the guard will be dropped.
667 match f(unsafe { orig.data.as_ref() }) {
668 Some(data) => {
669 let data = NonNull::from(data);
670 let orig = ManuallyDrop::new(orig);
671 Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
672 }
673 None => Err(orig),
674 }
675 }
676}
677
678impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
679 /// Creates a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
680 ///
681 /// # Safety
682 ///
683 /// This function is safe if and only if the same thread has successfully and safely called
684 /// `lock.inner.write()`, `lock.inner.try_write()`, or `lock.inner.try_upgrade` before
685 /// instantiating this object.
686 unsafe fn new(lock: &'rwlock RwLock<T>) -> RwLockWriteGuard<'rwlock, T> {
687 RwLockWriteGuard { lock }
688 }
689
690 /// Downgrades a write-locked `RwLockWriteGuard` into a read-locked [`RwLockReadGuard`].
691 ///
692 /// Since we have the `RwLockWriteGuard`, the [`RwLock`] must already be locked for writing, so
693 /// this method cannot fail.
694 ///
695 /// After downgrading, other readers will be allowed to read the protected data.
696 ///
697 /// # Examples
698 ///
699 /// `downgrade` takes ownership of the `RwLockWriteGuard` and returns a [`RwLockReadGuard`].
700 ///
701 /// ```
702 /// #![feature(nonpoison_rwlock)]
703 ///
704 /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
705 ///
706 /// let rw = RwLock::new(0);
707 ///
708 /// let mut write_guard = rw.write();
709 /// *write_guard = 42;
710 ///
711 /// let read_guard = RwLockWriteGuard::downgrade(write_guard);
712 /// assert_eq!(42, *read_guard);
713 /// ```
714 ///
715 /// `downgrade` will _atomically_ change the state of the [`RwLock`] from exclusive mode into
716 /// shared mode. This means that it is impossible for another writing thread to get in between a
717 /// thread calling `downgrade` and any reads it performs after downgrading.
718 ///
719 /// ```
720 /// #![feature(nonpoison_rwlock)]
721 ///
722 /// use std::sync::Arc;
723 /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
724 ///
725 /// let rw = Arc::new(RwLock::new(1));
726 ///
727 /// // Put the lock in write mode.
728 /// let mut main_write_guard = rw.write();
729 ///
730 /// let rw_clone = rw.clone();
731 /// let evil_handle = std::thread::spawn(move || {
732 /// // This will not return until the main thread drops the `main_read_guard`.
733 /// let mut evil_guard = rw_clone.write();
734 ///
735 /// assert_eq!(*evil_guard, 2);
736 /// *evil_guard = 3;
737 /// });
738 ///
739 /// *main_write_guard = 2;
740 ///
741 /// // Atomically downgrade the write guard into a read guard.
742 /// let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard);
743 ///
744 /// // Since `downgrade` is atomic, the writer thread cannot have changed the protected data.
745 /// assert_eq!(*main_read_guard, 2, "`downgrade` was not atomic");
746 /// #
747 /// # drop(main_read_guard);
748 /// # evil_handle.join().unwrap();
749 /// #
750 /// # let final_check = rw.read();
751 /// # assert_eq!(*final_check, 3);
752 /// ```
753 #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
754 pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
755 let lock = s.lock;
756
757 // We don't want to call the destructor since that calls `write_unlock`.
758 forget(s);
759
760 // SAFETY: We take ownership of a write guard, so we must already have the `RwLock` in write
761 // mode, satisfying the `downgrade` contract.
762 unsafe { lock.inner.downgrade() };
763
764 // SAFETY: We have just successfully called `downgrade`, so we fulfill the safety contract.
765 unsafe { RwLockReadGuard::new(lock) }
766 }
767
768 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g.
769 /// an enum variant.
770 ///
771 /// The `RwLock` is already locked for writing, so this cannot fail.
772 ///
773 /// This is an associated function that needs to be used as
774 /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of
775 /// the same name on the contents of the `RwLockWriteGuard` used through
776 /// `Deref`.
777 ///
778 /// # Panics
779 ///
780 /// If the closure panics, the guard will be dropped (unlocked).
781 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
782 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
783 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
784 where
785 F: FnOnce(&mut T) -> &mut U,
786 U: ?Sized,
787 {
788 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
789 // was created, and have been upheld throughout `map` and/or `filter_map`.
790 // The signature of the closure guarantees that it will not "leak" the lifetime of the
791 // reference passed to it. If the closure panics, the guard will be dropped.
792 let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
793 let orig = ManuallyDrop::new(orig);
794 MappedRwLockWriteGuard { data, inner_lock: &orig.lock.inner, _variance: PhantomData }
795 }
796
797 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The
798 /// original guard is returned as an `Err(...)` if the closure returns
799 /// `None`.
800 ///
801 /// The `RwLock` is already locked for writing, so this cannot fail.
802 ///
803 /// This is an associated function that needs to be used as
804 /// `RwLockWriteGuard::filter_map(...)`. A method would interfere with methods
805 /// of the same name on the contents of the `RwLockWriteGuard` used through
806 /// `Deref`.
807 ///
808 /// # Panics
809 ///
810 /// If the closure panics, the guard will be dropped (unlocked).
811 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
812 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
813 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
814 where
815 F: FnOnce(&mut T) -> Option<&mut U>,
816 U: ?Sized,
817 {
818 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
819 // was created, and have been upheld throughout `map` and/or `filter_map`.
820 // The signature of the closure guarantees that it will not "leak" the lifetime of the
821 // reference passed to it. If the closure panics, the guard will be dropped.
822 match f(unsafe { &mut *orig.lock.data.get() }) {
823 Some(data) => {
824 let data = NonNull::from(data);
825 let orig = ManuallyDrop::new(orig);
826 Ok(MappedRwLockWriteGuard {
827 data,
828 inner_lock: &orig.lock.inner,
829 _variance: PhantomData,
830 })
831 }
832 None => Err(orig),
833 }
834 }
835}
836
837impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> {
838 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data,
839 /// e.g. an enum variant.
840 ///
841 /// The `RwLock` is already locked for reading, so this cannot fail.
842 ///
843 /// This is an associated function that needs to be used as
844 /// `MappedRwLockReadGuard::map(...)`. A method would interfere with
845 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
846 /// used through `Deref`.
847 ///
848 /// # Panics
849 ///
850 /// If the closure panics, the guard will be dropped (unlocked).
851 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
852 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
853 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
854 where
855 F: FnOnce(&T) -> &U,
856 U: ?Sized,
857 {
858 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
859 // was created, and have been upheld throughout `map` and/or `filter_map`.
860 // The signature of the closure guarantees that it will not "leak" the lifetime of the
861 // reference passed to it. If the closure panics, the guard will be dropped.
862 let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
863 let orig = ManuallyDrop::new(orig);
864 MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
865 }
866
867 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data.
868 /// The original guard is returned as an `Err(...)` if the closure returns
869 /// `None`.
870 ///
871 /// The `RwLock` is already locked for reading, so this cannot fail.
872 ///
873 /// This is an associated function that needs to be used as
874 /// `MappedRwLockReadGuard::filter_map(...)`. A method would interfere with
875 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
876 /// used through `Deref`.
877 ///
878 /// # Panics
879 ///
880 /// If the closure panics, the guard will be dropped (unlocked).
881 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
882 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
883 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
884 where
885 F: FnOnce(&T) -> Option<&U>,
886 U: ?Sized,
887 {
888 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
889 // was created, and have been upheld throughout `map` and/or `filter_map`.
890 // The signature of the closure guarantees that it will not "leak" the lifetime of the
891 // reference passed to it. If the closure panics, the guard will be dropped.
892 match f(unsafe { orig.data.as_ref() }) {
893 Some(data) => {
894 let data = NonNull::from(data);
895 let orig = ManuallyDrop::new(orig);
896 Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
897 }
898 None => Err(orig),
899 }
900 }
901}
902
903impl<'rwlock, T: ?Sized> MappedRwLockWriteGuard<'rwlock, T> {
904 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data,
905 /// e.g. an enum variant.
906 ///
907 /// The `RwLock` is already locked for writing, so this cannot fail.
908 ///
909 /// This is an associated function that needs to be used as
910 /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with
911 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
912 /// used through `Deref`.
913 ///
914 /// # Panics
915 ///
916 /// If the closure panics, the guard will be dropped (unlocked).
917 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
918 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
919 pub fn map<U, F>(mut orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
920 where
921 F: FnOnce(&mut T) -> &mut U,
922 U: ?Sized,
923 {
924 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
925 // was created, and have been upheld throughout `map` and/or `filter_map`.
926 // The signature of the closure guarantees that it will not "leak" the lifetime of the
927 // reference passed to it. If the closure panics, the guard will be dropped.
928 let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
929 let orig = ManuallyDrop::new(orig);
930 MappedRwLockWriteGuard { data, inner_lock: orig.inner_lock, _variance: PhantomData }
931 }
932
933 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data.
934 /// The original guard is returned as an `Err(...)` if the closure returns
935 /// `None`.
936 ///
937 /// The `RwLock` is already locked for writing, so this cannot fail.
938 ///
939 /// This is an associated function that needs to be used as
940 /// `MappedRwLockWriteGuard::filter_map(...)`. A method would interfere with
941 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
942 /// used through `Deref`.
943 ///
944 /// # Panics
945 ///
946 /// If the closure panics, the guard will be dropped (unlocked).
947 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
948 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
949 pub fn filter_map<U, F>(
950 mut orig: Self,
951 f: F,
952 ) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
953 where
954 F: FnOnce(&mut T) -> Option<&mut U>,
955 U: ?Sized,
956 {
957 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
958 // was created, and have been upheld throughout `map` and/or `filter_map`.
959 // The signature of the closure guarantees that it will not "leak" the lifetime of the
960 // reference passed to it. If the closure panics, the guard will be dropped.
961 match f(unsafe { orig.data.as_mut() }) {
962 Some(data) => {
963 let data = NonNull::from(data);
964 let orig = ManuallyDrop::new(orig);
965 Ok(MappedRwLockWriteGuard {
966 data,
967 inner_lock: orig.inner_lock,
968 _variance: PhantomData,
969 })
970 }
971 None => Err(orig),
972 }
973 }
974}
975
976#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
977impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
978 fn drop(&mut self) {
979 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
980 unsafe {
981 self.inner_lock.read_unlock();
982 }
983 }
984}
985
986#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
987impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
988 fn drop(&mut self) {
989 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
990 unsafe {
991 self.lock.inner.write_unlock();
992 }
993 }
994}
995
996#[unstable(feature = "mapped_lock_guards", issue = "117108")]
997// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
998impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> {
999 fn drop(&mut self) {
1000 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
1001 // was created, and have been upheld throughout `map` and/or `filter_map`.
1002 unsafe {
1003 self.inner_lock.read_unlock();
1004 }
1005 }
1006}
1007
1008#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1009// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1010impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> {
1011 fn drop(&mut self) {
1012 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1013 // was created, and have been upheld throughout `map` and/or `filter_map`.
1014 unsafe {
1015 self.inner_lock.write_unlock();
1016 }
1017 }
1018}
1019
1020#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1021impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
1022 type Target = T;
1023
1024 fn deref(&self) -> &T {
1025 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
1026 unsafe { self.data.as_ref() }
1027 }
1028}
1029
1030#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1031impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
1032 type Target = T;
1033
1034 fn deref(&self) -> &T {
1035 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
1036 unsafe { &*self.lock.data.get() }
1037 }
1038}
1039
1040#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1041impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
1042 fn deref_mut(&mut self) -> &mut T {
1043 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
1044 unsafe { &mut *self.lock.data.get() }
1045 }
1046}
1047
1048#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1049// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1050impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> {
1051 type Target = T;
1052
1053 fn deref(&self) -> &T {
1054 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
1055 // was created, and have been upheld throughout `map` and/or `filter_map`.
1056 unsafe { self.data.as_ref() }
1057 }
1058}
1059
1060#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1061// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1062impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> {
1063 type Target = T;
1064
1065 fn deref(&self) -> &T {
1066 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1067 // was created, and have been upheld throughout `map` and/or `filter_map`.
1068 unsafe { self.data.as_ref() }
1069 }
1070}
1071
1072#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1073// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1074impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> {
1075 fn deref_mut(&mut self) -> &mut T {
1076 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1077 // was created, and have been upheld throughout `map` and/or `filter_map`.
1078 unsafe { self.data.as_mut() }
1079 }
1080}
1081
1082#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1083impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
1084 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1085 (**self).fmt(f)
1086 }
1087}
1088
1089#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1090impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
1091 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1092 (**self).fmt(f)
1093 }
1094}
1095
1096#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1097impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
1098 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1099 (**self).fmt(f)
1100 }
1101}
1102
1103#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1104impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
1105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1106 (**self).fmt(f)
1107 }
1108}
1109
1110#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1111// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1112impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> {
1113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1114 (**self).fmt(f)
1115 }
1116}
1117
1118#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1119// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1120impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> {
1121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1122 (**self).fmt(f)
1123 }
1124}
1125
1126#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1127// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1128impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> {
1129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1130 (**self).fmt(f)
1131 }
1132}
1133
1134#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1135// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1136impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> {
1137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1138 (**self).fmt(f)
1139 }
1140}