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 fn data_ptr(&self) -> *mut T {
499 self.data.get()
500 }
501}
502
503#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
504impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
505 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
506 let mut d = f.debug_struct("RwLock");
507 match self.try_read() {
508 Ok(guard) => {
509 d.field("data", &&*guard);
510 }
511 Err(WouldBlock) => {
512 d.field("data", &format_args!("<locked>"));
513 }
514 }
515 d.finish_non_exhaustive()
516 }
517}
518
519#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
520impl<T: Default> Default for RwLock<T> {
521 /// Creates a new `RwLock<T>`, with the `Default` value for T.
522 fn default() -> RwLock<T> {
523 RwLock::new(Default::default())
524 }
525}
526
527#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
528impl<T> From<T> for RwLock<T> {
529 /// Creates a new instance of an `RwLock<T>` which is unlocked.
530 /// This is equivalent to [`RwLock::new`].
531 fn from(t: T) -> Self {
532 RwLock::new(t)
533 }
534}
535
536impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
537 /// Creates a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
538 ///
539 /// # Safety
540 ///
541 /// This function is safe if and only if the same thread has successfully and safely called
542 /// `lock.inner.read()`, `lock.inner.try_read()`, or `lock.inner.downgrade()` before
543 /// instantiating this object.
544 unsafe fn new(lock: &'rwlock RwLock<T>) -> RwLockReadGuard<'rwlock, T> {
545 RwLockReadGuard {
546 data: unsafe { NonNull::new_unchecked(lock.data.get()) },
547 inner_lock: &lock.inner,
548 }
549 }
550
551 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data, e.g.
552 /// an enum variant.
553 ///
554 /// The `RwLock` is already locked for reading, so this cannot fail.
555 ///
556 /// This is an associated function that needs to be used as
557 /// `RwLockReadGuard::map(...)`. A method would interfere with methods of
558 /// the same name on the contents of the `RwLockReadGuard` used through
559 /// `Deref`.
560 ///
561 /// # Panics
562 ///
563 /// If the closure panics, the guard will be dropped (unlocked).
564 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
565 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
566 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
567 where
568 F: FnOnce(&T) -> &U,
569 U: ?Sized,
570 {
571 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
572 // was created, and have been upheld throughout `map` and/or `filter_map`.
573 // The signature of the closure guarantees that it will not "leak" the lifetime of the
574 // reference passed to it. If the closure panics, the guard will be dropped.
575 let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
576 let orig = ManuallyDrop::new(orig);
577 MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
578 }
579
580 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The
581 /// original guard is returned as an `Err(...)` if the closure returns
582 /// `None`.
583 ///
584 /// The `RwLock` is already locked for reading, so this cannot fail.
585 ///
586 /// This is an associated function that needs to be used as
587 /// `RwLockReadGuard::filter_map(...)`. A method would interfere with methods
588 /// of the same name on the contents of the `RwLockReadGuard` used through
589 /// `Deref`.
590 ///
591 /// # Panics
592 ///
593 /// If the closure panics, the guard will be dropped (unlocked).
594 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
595 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
596 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
597 where
598 F: FnOnce(&T) -> Option<&U>,
599 U: ?Sized,
600 {
601 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
602 // was created, and have been upheld throughout `map` and/or `filter_map`.
603 // The signature of the closure guarantees that it will not "leak" the lifetime of the
604 // reference passed to it. If the closure panics, the guard will be dropped.
605 match f(unsafe { orig.data.as_ref() }) {
606 Some(data) => {
607 let data = NonNull::from(data);
608 let orig = ManuallyDrop::new(orig);
609 Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
610 }
611 None => Err(orig),
612 }
613 }
614}
615
616impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
617 /// Creates a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
618 ///
619 /// # Safety
620 ///
621 /// This function is safe if and only if the same thread has successfully and safely called
622 /// `lock.inner.write()`, `lock.inner.try_write()`, or `lock.inner.try_upgrade` before
623 /// instantiating this object.
624 unsafe fn new(lock: &'rwlock RwLock<T>) -> RwLockWriteGuard<'rwlock, T> {
625 RwLockWriteGuard { lock }
626 }
627
628 /// Downgrades a write-locked `RwLockWriteGuard` into a read-locked [`RwLockReadGuard`].
629 ///
630 /// Since we have the `RwLockWriteGuard`, the [`RwLock`] must already be locked for writing, so
631 /// this method cannot fail.
632 ///
633 /// After downgrading, other readers will be allowed to read the protected data.
634 ///
635 /// # Examples
636 ///
637 /// `downgrade` takes ownership of the `RwLockWriteGuard` and returns a [`RwLockReadGuard`].
638 ///
639 /// ```
640 /// #![feature(nonpoison_rwlock)]
641 /// #![feature(rwlock_downgrade)]
642 ///
643 /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
644 ///
645 /// let rw = RwLock::new(0);
646 ///
647 /// let mut write_guard = rw.write();
648 /// *write_guard = 42;
649 ///
650 /// let read_guard = RwLockWriteGuard::downgrade(write_guard);
651 /// assert_eq!(42, *read_guard);
652 /// ```
653 ///
654 /// `downgrade` will _atomically_ change the state of the [`RwLock`] from exclusive mode into
655 /// shared mode. This means that it is impossible for another writing thread to get in between a
656 /// thread calling `downgrade` and any reads it performs after downgrading.
657 ///
658 /// ```
659 /// #![feature(nonpoison_rwlock)]
660 /// #![feature(rwlock_downgrade)]
661 ///
662 /// use std::sync::Arc;
663 /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
664 ///
665 /// let rw = Arc::new(RwLock::new(1));
666 ///
667 /// // Put the lock in write mode.
668 /// let mut main_write_guard = rw.write();
669 ///
670 /// let rw_clone = rw.clone();
671 /// let evil_handle = std::thread::spawn(move || {
672 /// // This will not return until the main thread drops the `main_read_guard`.
673 /// let mut evil_guard = rw_clone.write();
674 ///
675 /// assert_eq!(*evil_guard, 2);
676 /// *evil_guard = 3;
677 /// });
678 ///
679 /// *main_write_guard = 2;
680 ///
681 /// // Atomically downgrade the write guard into a read guard.
682 /// let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard);
683 ///
684 /// // Since `downgrade` is atomic, the writer thread cannot have changed the protected data.
685 /// assert_eq!(*main_read_guard, 2, "`downgrade` was not atomic");
686 /// #
687 /// # drop(main_read_guard);
688 /// # evil_handle.join().unwrap();
689 /// #
690 /// # let final_check = rw.read();
691 /// # assert_eq!(*final_check, 3);
692 /// ```
693 #[unstable(feature = "rwlock_downgrade", issue = "128203")]
694 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
695 pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
696 let lock = s.lock;
697
698 // We don't want to call the destructor since that calls `write_unlock`.
699 forget(s);
700
701 // SAFETY: We take ownership of a write guard, so we must already have the `RwLock` in write
702 // mode, satisfying the `downgrade` contract.
703 unsafe { lock.inner.downgrade() };
704
705 // SAFETY: We have just successfully called `downgrade`, so we fulfill the safety contract.
706 unsafe { RwLockReadGuard::new(lock) }
707 }
708
709 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data, e.g.
710 /// an enum variant.
711 ///
712 /// The `RwLock` is already locked for writing, so this cannot fail.
713 ///
714 /// This is an associated function that needs to be used as
715 /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of
716 /// the same name on the contents of the `RwLockWriteGuard` used through
717 /// `Deref`.
718 ///
719 /// # Panics
720 ///
721 /// If the closure panics, the guard will be dropped (unlocked).
722 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
723 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
724 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
725 where
726 F: FnOnce(&mut T) -> &mut U,
727 U: ?Sized,
728 {
729 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
730 // was created, and have been upheld throughout `map` and/or `filter_map`.
731 // The signature of the closure guarantees that it will not "leak" the lifetime of the
732 // reference passed to it. If the closure panics, the guard will be dropped.
733 let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
734 let orig = ManuallyDrop::new(orig);
735 MappedRwLockWriteGuard { data, inner_lock: &orig.lock.inner, _variance: PhantomData }
736 }
737
738 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data. The
739 /// original guard is returned as an `Err(...)` if the closure returns
740 /// `None`.
741 ///
742 /// The `RwLock` is already locked for writing, so this cannot fail.
743 ///
744 /// This is an associated function that needs to be used as
745 /// `RwLockWriteGuard::filter_map(...)`. A method would interfere with methods
746 /// of the same name on the contents of the `RwLockWriteGuard` used through
747 /// `Deref`.
748 ///
749 /// # Panics
750 ///
751 /// If the closure panics, the guard will be dropped (unlocked).
752 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
753 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
754 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
755 where
756 F: FnOnce(&mut T) -> Option<&mut U>,
757 U: ?Sized,
758 {
759 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
760 // was created, and have been upheld throughout `map` and/or `filter_map`.
761 // The signature of the closure guarantees that it will not "leak" the lifetime of the
762 // reference passed to it. If the closure panics, the guard will be dropped.
763 match f(unsafe { &mut *orig.lock.data.get() }) {
764 Some(data) => {
765 let data = NonNull::from(data);
766 let orig = ManuallyDrop::new(orig);
767 Ok(MappedRwLockWriteGuard {
768 data,
769 inner_lock: &orig.lock.inner,
770 _variance: PhantomData,
771 })
772 }
773 None => Err(orig),
774 }
775 }
776}
777
778impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> {
779 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data,
780 /// e.g. an enum variant.
781 ///
782 /// The `RwLock` is already locked for reading, so this cannot fail.
783 ///
784 /// This is an associated function that needs to be used as
785 /// `MappedRwLockReadGuard::map(...)`. A method would interfere with
786 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
787 /// used through `Deref`.
788 ///
789 /// # Panics
790 ///
791 /// If the closure panics, the guard will be dropped (unlocked).
792 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
793 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
794 pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
795 where
796 F: FnOnce(&T) -> &U,
797 U: ?Sized,
798 {
799 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
800 // was created, and have been upheld throughout `map` and/or `filter_map`.
801 // The signature of the closure guarantees that it will not "leak" the lifetime of the
802 // reference passed to it. If the closure panics, the guard will be dropped.
803 let data = NonNull::from(f(unsafe { orig.data.as_ref() }));
804 let orig = ManuallyDrop::new(orig);
805 MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }
806 }
807
808 /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data.
809 /// The original guard is returned as an `Err(...)` if the closure returns
810 /// `None`.
811 ///
812 /// The `RwLock` is already locked for reading, so this cannot fail.
813 ///
814 /// This is an associated function that needs to be used as
815 /// `MappedRwLockReadGuard::filter_map(...)`. A method would interfere with
816 /// methods of the same name on the contents of the `MappedRwLockReadGuard`
817 /// used through `Deref`.
818 ///
819 /// # Panics
820 ///
821 /// If the closure panics, the guard will be dropped (unlocked).
822 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
823 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
824 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
825 where
826 F: FnOnce(&T) -> Option<&U>,
827 U: ?Sized,
828 {
829 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
830 // was created, and have been upheld throughout `map` and/or `filter_map`.
831 // The signature of the closure guarantees that it will not "leak" the lifetime of the
832 // reference passed to it. If the closure panics, the guard will be dropped.
833 match f(unsafe { orig.data.as_ref() }) {
834 Some(data) => {
835 let data = NonNull::from(data);
836 let orig = ManuallyDrop::new(orig);
837 Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock })
838 }
839 None => Err(orig),
840 }
841 }
842}
843
844impl<'rwlock, T: ?Sized> MappedRwLockWriteGuard<'rwlock, T> {
845 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data,
846 /// e.g. an enum variant.
847 ///
848 /// The `RwLock` is already locked for writing, so this cannot fail.
849 ///
850 /// This is an associated function that needs to be used as
851 /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with
852 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
853 /// used through `Deref`.
854 ///
855 /// # Panics
856 ///
857 /// If the closure panics, the guard will be dropped (unlocked).
858 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
859 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
860 pub fn map<U, F>(mut orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
861 where
862 F: FnOnce(&mut T) -> &mut U,
863 U: ?Sized,
864 {
865 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
866 // was created, and have been upheld throughout `map` and/or `filter_map`.
867 // The signature of the closure guarantees that it will not "leak" the lifetime of the
868 // reference passed to it. If the closure panics, the guard will be dropped.
869 let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
870 let orig = ManuallyDrop::new(orig);
871 MappedRwLockWriteGuard { data, inner_lock: orig.inner_lock, _variance: PhantomData }
872 }
873
874 /// Makes a [`MappedRwLockWriteGuard`] for a component of the borrowed data.
875 /// The original guard is returned as an `Err(...)` if the closure returns
876 /// `None`.
877 ///
878 /// The `RwLock` is already locked for writing, so this cannot fail.
879 ///
880 /// This is an associated function that needs to be used as
881 /// `MappedRwLockWriteGuard::filter_map(...)`. A method would interfere with
882 /// methods of the same name on the contents of the `MappedRwLockWriteGuard`
883 /// used through `Deref`.
884 ///
885 /// # Panics
886 ///
887 /// If the closure panics, the guard will be dropped (unlocked).
888 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
889 // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
890 pub fn filter_map<U, F>(
891 mut orig: Self,
892 f: F,
893 ) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
894 where
895 F: FnOnce(&mut T) -> Option<&mut U>,
896 U: ?Sized,
897 {
898 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
899 // was created, and have been upheld throughout `map` and/or `filter_map`.
900 // The signature of the closure guarantees that it will not "leak" the lifetime of the
901 // reference passed to it. If the closure panics, the guard will be dropped.
902 match f(unsafe { orig.data.as_mut() }) {
903 Some(data) => {
904 let data = NonNull::from(data);
905 let orig = ManuallyDrop::new(orig);
906 Ok(MappedRwLockWriteGuard {
907 data,
908 inner_lock: orig.inner_lock,
909 _variance: PhantomData,
910 })
911 }
912 None => Err(orig),
913 }
914 }
915}
916
917#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
918impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
919 fn drop(&mut self) {
920 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
921 unsafe {
922 self.inner_lock.read_unlock();
923 }
924 }
925}
926
927#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
928impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
929 fn drop(&mut self) {
930 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
931 unsafe {
932 self.lock.inner.write_unlock();
933 }
934 }
935}
936
937#[unstable(feature = "mapped_lock_guards", issue = "117108")]
938// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
939impl<T: ?Sized> Drop for MappedRwLockReadGuard<'_, T> {
940 fn drop(&mut self) {
941 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
942 // was created, and have been upheld throughout `map` and/or `filter_map`.
943 unsafe {
944 self.inner_lock.read_unlock();
945 }
946 }
947}
948
949#[unstable(feature = "mapped_lock_guards", issue = "117108")]
950// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
951impl<T: ?Sized> Drop for MappedRwLockWriteGuard<'_, T> {
952 fn drop(&mut self) {
953 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
954 // was created, and have been upheld throughout `map` and/or `filter_map`.
955 unsafe {
956 self.inner_lock.write_unlock();
957 }
958 }
959}
960
961#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
962impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
963 type Target = T;
964
965 fn deref(&self) -> &T {
966 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when created.
967 unsafe { self.data.as_ref() }
968 }
969}
970
971#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
972impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
973 type Target = T;
974
975 fn deref(&self) -> &T {
976 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
977 unsafe { &*self.lock.data.get() }
978 }
979}
980
981#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
982impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
983 fn deref_mut(&mut self) -> &mut T {
984 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when created.
985 unsafe { &mut *self.lock.data.get() }
986 }
987}
988
989#[unstable(feature = "mapped_lock_guards", issue = "117108")]
990// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
991impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T> {
992 type Target = T;
993
994 fn deref(&self) -> &T {
995 // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard
996 // was created, and have been upheld throughout `map` and/or `filter_map`.
997 unsafe { self.data.as_ref() }
998 }
999}
1000
1001#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1002// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1003impl<T: ?Sized> Deref for MappedRwLockWriteGuard<'_, T> {
1004 type Target = T;
1005
1006 fn deref(&self) -> &T {
1007 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1008 // was created, and have been upheld throughout `map` and/or `filter_map`.
1009 unsafe { self.data.as_ref() }
1010 }
1011}
1012
1013#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1014// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1015impl<T: ?Sized> DerefMut for MappedRwLockWriteGuard<'_, T> {
1016 fn deref_mut(&mut self) -> &mut T {
1017 // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard
1018 // was created, and have been upheld throughout `map` and/or `filter_map`.
1019 unsafe { self.data.as_mut() }
1020 }
1021}
1022
1023#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1024impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
1025 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1026 (**self).fmt(f)
1027 }
1028}
1029
1030#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1031impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
1032 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1033 (**self).fmt(f)
1034 }
1035}
1036
1037#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1038impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
1039 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1040 (**self).fmt(f)
1041 }
1042}
1043
1044#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1045impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
1046 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1047 (**self).fmt(f)
1048 }
1049}
1050
1051#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1052// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1053impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockReadGuard<'_, T> {
1054 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1055 (**self).fmt(f)
1056 }
1057}
1058
1059#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1060// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1061impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockReadGuard<'_, T> {
1062 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1063 (**self).fmt(f)
1064 }
1065}
1066
1067#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1068// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1069impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedRwLockWriteGuard<'_, T> {
1070 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1071 (**self).fmt(f)
1072 }
1073}
1074
1075#[unstable(feature = "mapped_lock_guards", issue = "117108")]
1076// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
1077impl<T: ?Sized + fmt::Display> fmt::Display for MappedRwLockWriteGuard<'_, T> {
1078 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1079 (**self).fmt(f)
1080 }
1081}