Skip to content

Commit a8e71f2

Browse files
committed
doc: update thread safety explanation for RawWakerVTable and RawWaker.
1 parent 3e373f5 commit a8e71f2

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

library/core/src/task/wake.rs

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::marker::PhantomData;
77
use crate::ptr;
88

99
/// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
10-
/// which provides customized wakeup behavior.
10+
/// or a [`LocalWaker`] which provides customized wakeup behavior.
1111
///
1212
/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table
1313
///
@@ -35,9 +35,18 @@ impl RawWaker {
3535
/// The value of this pointer will get passed to all functions that are part
3636
/// of the `vtable` as the first parameter.
3737
///
38+
/// It is important to consider that the `data` pointer must point to a
39+
/// thread safe type such as an `[Arc]<T: Send + Sync>`
40+
/// when used to construct a [`Waker`]. This restriction is lifted when
41+
/// constructing a [`LocalWaker`], which allows using types that do not implement
42+
/// <code>[Send] + [Sync]</code> like `[Rc]<T: !Send + !Sync>`.
43+
///
3844
/// The `vtable` customizes the behavior of a `Waker` which gets created
3945
/// from a `RawWaker`. For each operation on the `Waker`, the associated
4046
/// function in the `vtable` of the underlying `RawWaker` will be called.
47+
///
48+
/// [`Arc`]: std::sync::Arc
49+
/// [`Rc`]: std::rc::Rc
4150
#[inline]
4251
#[rustc_promotable]
4352
#[stable(feature = "futures_api", since = "1.36.0")]
@@ -90,11 +99,19 @@ impl RawWaker {
9099
/// [`RawWaker`] implementation. Calling one of the contained functions using
91100
/// any other `data` pointer will cause undefined behavior.
92101
///
93-
/// These functions must all be thread-safe (even though [`RawWaker`] is
94-
/// <code>\![Send] + \![Sync]</code>)
95-
/// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to
96-
/// arbitrary threads or invoked by `&` reference. For example, this means that if the
97-
/// `clone` and `drop` functions manage a reference count, they must do so atomically.
102+
/// # Thread safety
103+
/// If the [`RawWaker`] will be used to construct a [`Waker`] then
104+
/// these functions must all be thread-safe (even though [`RawWaker`] is
105+
/// <code>\![Send] + \![Sync]</code>). This is because [`Waker`] is <code>[Send] + [Sync]</code>,
106+
/// and it may be moved to arbitrary threads or invoked by `&` reference. For example,
107+
/// this means that if the `clone` and `drop` functions manage a reference count,
108+
/// they must do so atomically.
109+
///
110+
/// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then
111+
/// these functions don't need to be thread safe. This means that <code>\![Send] + \![Sync]</code>
112+
/// data can be stored in the data pointer, and reference counting does not need any atomic
113+
/// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot
114+
/// be sent across threads.
98115
#[stable(feature = "futures_api", since = "1.36.0")]
99116
#[derive(PartialEq, Copy, Clone, Debug)]
100117
pub struct RawWakerVTable {
@@ -134,16 +151,22 @@ impl RawWakerVTable {
134151
/// Creates a new `RawWakerVTable` from the provided `clone`, `wake`,
135152
/// `wake_by_ref`, and `drop` functions.
136153
///
137-
/// These functions must all be thread-safe (even though [`RawWaker`] is
138-
/// <code>\![Send] + \![Sync]</code>)
139-
/// because [`Waker`] is <code>[Send] + [Sync]</code>, and thus wakers may be moved to
140-
/// arbitrary threads or invoked by `&` reference. For example, this means that if the
141-
/// `clone` and `drop` functions manage a reference count, they must do so atomically.
142-
///
154+
/// If the [`RawWaker`] will be used to construct a [`Waker`] then
155+
/// these functions must all be thread-safe (even though [`RawWaker`] is
156+
/// <code>\![Send] + \![Sync]</code>). This is because [`Waker`] is <code>[Send] + [Sync]</code>,
157+
/// and it may be moved to arbitrary threads or invoked by `&` reference. For example,
158+
/// this means that if the `clone` and `drop` functions manage a reference count,
159+
/// they must do so atomically.
160+
///
161+
/// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then
162+
/// these functions don't need to be thread safe. This means that <code>\![Send] + \![Sync]</code>
163+
/// data can be stored in the data pointer, and reference counting does not need any atomic
164+
/// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot
165+
/// be sent across threads.
143166
/// # `clone`
144167
///
145168
/// This function will be called when the [`RawWaker`] gets cloned, e.g. when
146-
/// the [`Waker`] in which the [`RawWaker`] is stored gets cloned.
169+
/// the [`Waker`]/[`LocalWaker`] in which the [`RawWaker`] is stored gets cloned.
147170
///
148171
/// The implementation of this function must retain all resources that are
149172
/// required for this additional instance of a [`RawWaker`] and associated
@@ -169,7 +192,7 @@ impl RawWakerVTable {
169192
///
170193
/// # `drop`
171194
///
172-
/// This function gets called when a [`Waker`] gets dropped.
195+
/// This function gets called when a [`Waker`]/[`LocalWaker`] gets dropped.
173196
///
174197
/// The implementation of this function must make sure to release any
175198
/// resources that are associated with this instance of a [`RawWaker`] and
@@ -335,13 +358,13 @@ impl<'a> ContextBuilder<'a> {
335358
}
336359
}
337360

338-
/// Construct a `ContextBuilder`` from a `Context`. This is useful for
361+
/// Construct a [`ContextBuilder`] from a [`Context`]. This is useful for
339362
/// overriding values from a context.
340363
///
341364
/// # Examples
342-
/// An example of a future that allows to set a Waker on Context if none was defined.
343-
/// This can be used to await futures that require a `Waker` even if the runtime does not
344-
/// support `Waker`.
365+
/// An example of a future that allows to set a [`Waker`] on Context if none was defined.
366+
/// This can be used to await futures that require a [`Waker`] even if the runtime does not
367+
/// support [`Waker`].
345368
/// ```rust
346369
/// #![feature(noop_waker, local_waker)]
347370
/// use std::task::{Waker, ContextBuilder};
@@ -596,7 +619,7 @@ impl fmt::Debug for Waker {
596619
/// unnecessarily if the two wakers [wake the same task](Self::will_wake).
597620
///
598621
/// # Examples
599-
/// Usage of a local waker to implement a future
622+
/// Usage of a local waker to implement a future analogous to `std::thread::yield_now()`.
600623
/// ```
601624
/// #![feature(local_waker)]
602625
/// use std::future::{Future, poll_fn};
@@ -623,6 +646,7 @@ impl fmt::Debug for Waker {
623646
/// [`Future::poll()`]: core::future::Future::poll
624647
/// [`Poll::Pending`]: core::task::Poll::Pending
625648
/// [`local_waker`]: core::task::Context::local_waker
649+
626650
#[unstable(feature = "local_waker", issue = "118959")]
627651
#[repr(transparent)]
628652
pub struct LocalWaker {

0 commit comments

Comments
 (0)