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 /// #![feature(rwlock_downgrade)]
704 ///
705 /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
706 ///
707 /// let rw = RwLock::new(0);
708 ///
709 /// let mut write_guard = rw.write();
710 /// *write_guard = 42;
711 ///
712 /// let read_guard = RwLockWriteGuard::downgrade(write_guard);
713 /// assert_eq!(42, *read_guard);
714 /// ```
715 ///
716 /// `downgrade` will _atomically_ change the state of the [`RwLock`] from exclusive mode into
717 /// shared mode. This means that it is impossible for another writing thread to get in between a
718 /// thread calling `downgrade` and any reads it performs after downgrading.
719 ///
720 /// ```
721 /// #![feature(nonpoison_rwlock)]
722 /// #![feature(rwlock_downgrade)]
723 ///
724 /// use std::sync::Arc;
725 /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
726 ///
727 /// let rw = Arc::new(RwLock::new(1));
728 ///
729 /// // Put the lock in write mode.
730 /// let mut main_write_guard = rw.write();
731 ///
732 /// let rw_clone = rw.clone();
733 /// let evil_handle = std::thread::spawn(move || {
734 /// // This will not return until the main thread drops the `main_read_guard`.
735 /// let mut evil_guard = rw_clone.write();
736 ///
737 /// assert_eq!(*evil_guard, 2);
738 /// *evil_guard = 3;
739 /// });
740 ///
741 /// *main_write_guard = 2;
742 ///
743 /// // Atomically downgrade the write guard into a read guard.
744 /// let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard);
745 ///
746 /// // Since `downgrade` is atomic, the writer thread cannot have changed the protected data.
747 /// assert_eq!(*main_read_guard, 2, "`downgrade` was not atomic");
748 /// #
749 /// # drop(main_read_guard);
750 /// # evil_handle.join().unwrap();
751 /// #
752 /// # let final_check = rw.read();
753 /// # assert_eq!(*final_check, 3);
754 /// ```
755 #[unstable(feature = "rwlock_downgrade", issue = "128203")]
756 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
757 pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
758 let lock = s.lock;
759
760 // We don't want to call the destructor since that calls `write_unlock`.
761 forget(s);
762
763 // SAFETY: We take ownership of a write guard, so we must already have the `RwLock` in write
764 // mode, satisfying the `downgrade` contract.
765 unsafe { lock.inner.downgrade() };
766
767 // SAFETY: We have just successfully called `downgrade`, so we fulfill the safety contract.
768 unsafe { RwLockReadGuard::new(lock) }
769 }
770
771 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g.
772 /// an enum variant.
773 ///
774 /// The `RwLock` is already locked for writing, so this cannot fail.
775 ///
776 /// This is an associated function that needs to be used as
777 /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of
778 /// the same name on the contents of the `RwLockWriteGuard` used through
779 /// `Deref`.
780 ///
781 /// # Panics
782 ///
783 /// If the closure panics, the guard will be dropped (unlocked).
784 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
785 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
786 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
787 where
788 F: FnOnce(&mut T) -> &mut U,
789 U: ?Sized,
790 {
791 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
792 // was created, and have been upheld throughout `map` and/or `filter_map`.
793 // The signature of the closure guarantees that it will not "leak" the lifetime of the
794 // reference passed to it. If the closure panics, the guard will be dropped.
795 let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
796 let orig = ManuallyDrop::new(orig);
797 MappedRwLockWriteGuard { data, inner_lock: &orig.lock.inner, _variance: PhantomData }
798 }
799
800 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The
801 /// original guard is returned as an `Err(...)` if the closure returns
802 /// `None`.
803 ///
804 /// The `RwLock` is already locked for writing, so this cannot fail.
805 ///
806 /// This is an associated function that needs to be used as
807 /// `RwLockWriteGuard::filter_map(...)`. A method would interfere with methods
808 /// of the same name on the contents of the `RwLockWriteGuard` used through
809 /// `Deref`.
810 ///
811 /// # Panics
812 ///
813 /// If the closure panics, the guard will be dropped (unlocked).
814 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
815 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
816 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
817 where
818 F: FnOnce(&mut T) -> Option<&mut U>,
819 U: ?Sized,
820 {
821 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
822 // was created, and have been upheld throughout `map` and/or `filter_map`.
823 // The signature of the closure guarantees that it will not "leak" the lifetime of the
824 // reference passed to it. If the closure panics, the guard will be dropped.
825 match f(unsafe { &mut *orig.lock.data.get() }) {
826 Some(data) => {
827 let data = NonNull::from(data);
828 let orig = ManuallyDrop::new(orig);
829 Ok(MappedRwLockWriteGuard {
830 data,
831 inner_lock: &orig.lock.inner,
832 _variance: PhantomData,
833 })
834 }
835 None => Err(orig),
836 }
837 }
838}
839
840impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> {
841 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data,
842 /// e.g. an enum variant.
843 ///
844 /// The `RwLock` is already locked for reading, so this cannot fail.
845 ///
846 /// This is an associated function that needs to be used as
847 /// `MappedRwLockReadGuard::map(...)`. A method would interfere with
848 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
849 /// used through `Deref`.
850 ///
851 /// # Panics
852 ///
853 /// If the closure panics, the guard will be dropped (unlocked).
854 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
855 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
856 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
857 where
858 F: FnOnce(&T) -> &U,
859 U: ?Sized,
860 {
861 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
862 // was created, and have been upheld throughout `map` and/or `filter_map`.
863 // The signature of the closure guarantees that it will not "leak" the lifetime of the
864 // reference passed to it. If the closure panics, the guard will be dropped.
865 let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
866 let orig = ManuallyDrop::new(orig);
867 MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
868 }
869
870 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data.
871 /// The original guard is returned as an `Err(...)` if the closure returns
872 /// `None`.
873 ///
874 /// The `RwLock` is already locked for reading, so this cannot fail.
875 ///
876 /// This is an associated function that needs to be used as
877 /// `MappedRwLockReadGuard::filter_map(...)`. A method would interfere with
878 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
879 /// used through `Deref`.
880 ///
881 /// # Panics
882 ///
883 /// If the closure panics, the guard will be dropped (unlocked).
884 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
885 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
886 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
887 where
888 F: FnOnce(&T) -> Option<&U>,
889 U: ?Sized,
890 {
891 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
892 // was created, and have been upheld throughout `map` and/or `filter_map`.
893 // The signature of the closure guarantees that it will not "leak" the lifetime of the
894 // reference passed to it. If the closure panics, the guard will be dropped.
895 match f(unsafe { orig.data.as_ref() }) {
896 Some(data) => {
897 let data = NonNull::from(data);
898 let orig = ManuallyDrop::new(orig);
899 Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
900 }
901 None => Err(orig),
902 }
903 }
904}
905
906impl<'rwlock, T: ?Sized> MappedRwLockWriteGuard<'rwlock, T> {
907 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data,
908 /// e.g. an enum variant.
909 ///
910 /// The `RwLock` is already locked for writing, so this cannot fail.
911 ///
912 /// This is an associated function that needs to be used as
913 /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with
914 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
915 /// used through `Deref`.
916 ///
917 /// # Panics
918 ///
919 /// If the closure panics, the guard will be dropped (unlocked).
920 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
921 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
922 pub fn map<U, F>(mut orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
923 where
924 F: FnOnce(&mut T) -> &mut U,
925 U: ?Sized,
926 {
927 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
928 // was created, and have been upheld throughout `map` and/or `filter_map`.
929 // The signature of the closure guarantees that it will not "leak" the lifetime of the
930 // reference passed to it. If the closure panics, the guard will be dropped.
931 let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
932 let orig = ManuallyDrop::new(orig);
933 MappedRwLockWriteGuard { data, inner_lock: orig.inner_lock, _variance: PhantomData }
934 }
935
936 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data.
937 /// The original guard is returned as an `Err(...)` if the closure returns
938 /// `None`.
939 ///
940 /// The `RwLock` is already locked for writing, so this cannot fail.
941 ///
942 /// This is an associated function that needs to be used as
943 /// `MappedRwLockWriteGuard::filter_map(...)`. A method would interfere with
944 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
945 /// used through `Deref`.
946 ///
947 /// # Panics
948 ///
949 /// If the closure panics, the guard will be dropped (unlocked).
950 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
951 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
952 pub fn filter_map<U, F>(
953 mut orig: Self,
954 f: F,
955 ) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
956 where
957 F: FnOnce(&mut T) -> Option<&mut U>,
958 U: ?Sized,
959 {
960 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
961 // was created, and have been upheld throughout `map` and/or `filter_map`.
962 // The signature of the closure guarantees that it will not "leak" the lifetime of the
963 // reference passed to it. If the closure panics, the guard will be dropped.
964 match f(unsafe { orig.data.as_mut() }) {
965 Some(data) => {
966 let data = NonNull::from(data);
967 let orig = ManuallyDrop::new(orig);
968 Ok(MappedRwLockWriteGuard {
969 data,
970 inner_lock: orig.inner_lock,
971 _variance: PhantomData,
972 })
973 }
974 None => Err(orig),
975 }
976 }
977}
978
979#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
980impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
981 fn drop(&mut self) {
982 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
983 unsafe {
984 self.inner_lock.read_unlock();
985 }
986 }
987}
988
989#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
990impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
991 fn drop(&mut self) {
992 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
993 unsafe {
994 self.lock.inner.write_unlock();
995 }
996 }
997}
998
999#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1000// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1001impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> {
1002 fn drop(&mut self) {
1003 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
1004 // was created, and have been upheld throughout `map` and/or `filter_map`.
1005 unsafe {
1006 self.inner_lock.read_unlock();
1007 }
1008 }
1009}
1010
1011#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1012// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1013impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> {
1014 fn drop(&mut self) {
1015 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1016 // was created, and have been upheld throughout `map` and/or `filter_map`.
1017 unsafe {
1018 self.inner_lock.write_unlock();
1019 }
1020 }
1021}
1022
1023#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1024impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
1025 type Target = T;
1026
1027 fn deref(&self) -> &T {
1028 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
1029 unsafe { self.data.as_ref() }
1030 }
1031}
1032
1033#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1034impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
1035 type Target = T;
1036
1037 fn deref(&self) -> &T {
1038 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
1039 unsafe { &*self.lock.data.get() }
1040 }
1041}
1042
1043#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1044impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
1045 fn deref_mut(&mut self) -> &mut T {
1046 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
1047 unsafe { &mut *self.lock.data.get() }
1048 }
1049}
1050
1051#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1052// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1053impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> {
1054 type Target = T;
1055
1056 fn deref(&self) -> &T {
1057 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
1058 // was created, and have been upheld throughout `map` and/or `filter_map`.
1059 unsafe { self.data.as_ref() }
1060 }
1061}
1062
1063#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1064// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1065impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> {
1066 type Target = T;
1067
1068 fn deref(&self) -> &T {
1069 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1070 // was created, and have been upheld throughout `map` and/or `filter_map`.
1071 unsafe { self.data.as_ref() }
1072 }
1073}
1074
1075#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1076// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1077impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> {
1078 fn deref_mut(&mut self) -> &mut T {
1079 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1080 // was created, and have been upheld throughout `map` and/or `filter_map`.
1081 unsafe { self.data.as_mut() }
1082 }
1083}
1084
1085#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1086impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
1087 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1088 (**self).fmt(f)
1089 }
1090}
1091
1092#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1093impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
1094 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1095 (**self).fmt(f)
1096 }
1097}
1098
1099#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1100impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
1101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1102 (**self).fmt(f)
1103 }
1104}
1105
1106#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1107impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
1108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1109 (**self).fmt(f)
1110 }
1111}
1112
1113#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1114// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1115impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> {
1116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1117 (**self).fmt(f)
1118 }
1119}
1120
1121#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1122// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1123impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> {
1124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1125 (**self).fmt(f)
1126 }
1127}
1128
1129#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1130// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1131impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> {
1132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1133 (**self).fmt(f)
1134 }
1135}
1136
1137#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1138// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1139impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> {
1140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1141 (**self).fmt(f)
1142 }
1143}