Skip to content

Commit 038c6e0

Browse files
committed
refactor: make waker mandatory.
This also removes * impl From<&Context> for ContextBuilder * Context::try_waker() The from implementation is removed because now that wakers are always supported, there are less incentives to override the current context. Before, the incentive was to add Waker support to a reactor that didn't have any.
1 parent 7c6a9cb commit 038c6e0

File tree

2 files changed

+28
-87
lines changed

2 files changed

+28
-87
lines changed

library/alloc/src/task.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,16 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
173173
///
174174
/// This is a simplified example of a `spawn` and a `block_on` function. The `spawn` function
175175
/// is used to push new tasks onto the run queue, while the block on function will remove them
176-
/// and poll them. When a task is woken, it will put itself back on the run queue to be polled by the executor.
176+
/// and poll them. When a task is woken, it will put itself back on the run queue to be polled
177+
/// by the executor.
177178
///
178-
/// **Note:** A real world example would interleave poll calls with calls to an io reactor to wait for events instead
179-
/// of spinning on a loop.
179+
/// **Note:** This example trades correctness for simplicity. A real world example would interleave
180+
/// poll calls with calls to an io reactor to wait for events instead of spinning on a loop.
180181
///
181182
/// ```rust
182183
/// #![feature(local_waker)]
183-
/// use std::task::{LocalWake, ContextBuilder, LocalWaker};
184+
/// #![feature(noop_waker)]
185+
/// use std::task::{LocalWake, ContextBuilder, LocalWaker, Waker};
184186
/// use std::future::Future;
185187
/// use std::pin::Pin;
186188
/// use std::rc::Rc;
@@ -225,10 +227,12 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
225227
/// // we exit, since there are no more tasks remaining on the queue
226228
/// return;
227229
/// };
230+
/// let waker = Waker::noop();
228231
/// // cast the Rc<Task> into a `LocalWaker`
229-
/// let waker: LocalWaker = task.clone().into();
232+
/// let local_waker: LocalWaker = task.clone().into();
230233
/// // Build the context using `ContextBuilder`
231-
/// let mut cx = ContextBuilder::from_local_waker(&waker)
234+
/// let mut cx = ContextBuilder::from_waker(&waker)
235+
/// .local_waker(&local_waker)
232236
/// .build();
233237
///
234238
/// // Poll the task

library/core/src/task/wake.rs

+18-81
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl RawWakerVTable {
217217
#[stable(feature = "futures_api", since = "1.36.0")]
218218
#[lang = "Context"]
219219
pub struct Context<'a> {
220-
waker: Option<&'a Waker>,
220+
waker: &'a Waker,
221221
local_waker: &'a LocalWaker,
222222
// Ensure we future-proof against variance changes by forcing
223223
// the lifetime to be invariant (argument-position lifetimes
@@ -245,9 +245,7 @@ impl<'a> Context<'a> {
245245
#[stable(feature = "futures_api", since = "1.36.0")]
246246
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
247247
pub const fn waker(&self) -> &'a Waker {
248-
&self
249-
.waker
250-
.expect("no waker was set on this context, consider calling `local_waker` instead.")
248+
&self.waker
251249
}
252250
/// Returns a reference to the [`LocalWaker`] for the current task.
253251
#[inline]
@@ -256,14 +254,6 @@ impl<'a> Context<'a> {
256254
pub const fn local_waker(&self) -> &'a LocalWaker {
257255
&self.local_waker
258256
}
259-
/// Returns a `Some(&Waker)` if a waker was defined on the `Context`,
260-
/// otherwise it returns `None`.
261-
#[inline]
262-
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
263-
#[unstable(feature = "local_waker", issue = "118959")]
264-
pub const fn try_waker(&self) -> Option<&'a Waker> {
265-
self.waker
266-
}
267257
}
268258

269259
#[stable(feature = "futures_api", since = "1.36.0")]
@@ -286,8 +276,8 @@ impl fmt::Debug for Context<'_> {
286276
/// let local_waker = LocalWaker::noop();
287277
/// let waker = Waker::noop();
288278
///
289-
/// let mut cx = ContextBuilder::from_local_waker(&local_waker)
290-
/// .waker(&waker)
279+
/// let mut cx = ContextBuilder::from_waker(&waker)
280+
/// .local_waker(&local_waker)
291281
/// .build();
292282
///
293283
/// let mut future = std::pin::pin!(async { 20 });
@@ -298,8 +288,16 @@ impl fmt::Debug for Context<'_> {
298288
#[unstable(feature = "local_waker", issue = "118959")]
299289
#[derive(Debug)]
300290
pub struct ContextBuilder<'a> {
301-
waker: Option<&'a Waker>,
291+
waker: &'a Waker,
302292
local_waker: &'a LocalWaker,
293+
// Ensure we future-proof against variance changes by forcing
294+
// the lifetime to be invariant (argument-position lifetimes
295+
// are contravariant while return-position lifetimes are
296+
// covariant).
297+
_marker: PhantomData<fn(&'a ()) -> &'a ()>,
298+
// Ensure `Context` is `!Send` and `!Sync` in order to allow
299+
// for future `!Send` and / or `!Sync` fields.
300+
_marker2: PhantomData<*mut ()>,
303301
}
304302

305303
impl<'a> ContextBuilder<'a> {
@@ -310,23 +308,7 @@ impl<'a> ContextBuilder<'a> {
310308
pub const fn from_waker(waker: &'a Waker) -> Self {
311309
// SAFETY: LocalWaker is just Waker without thread safety
312310
let local_waker = unsafe { transmute(waker) };
313-
Self { waker: Some(waker), local_waker }
314-
}
315-
316-
/// Create a ContextBuilder from a LocalWaker.
317-
#[inline]
318-
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
319-
#[unstable(feature = "local_waker", issue = "118959")]
320-
pub const fn from_local_waker(local_waker: &'a LocalWaker) -> Self {
321-
Self { local_waker, waker: None }
322-
}
323-
324-
/// This field is used to set the value of the waker on `Context`.
325-
#[inline]
326-
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
327-
#[unstable(feature = "local_waker", issue = "118959")]
328-
pub const fn waker(self, waker: &'a Waker) -> Self {
329-
Self { waker: Some(waker), ..self }
311+
Self { waker: waker, local_waker, _marker: PhantomData, _marker2: PhantomData }
330312
}
331313

332314
/// This method is used to set the value for the local waker on `Context`.
@@ -342,52 +324,8 @@ impl<'a> ContextBuilder<'a> {
342324
#[unstable(feature = "local_waker", issue = "118959")]
343325
#[rustc_const_unstable(feature = "const_waker", issue = "102012")]
344326
pub const fn build(self) -> Context<'a> {
345-
let ContextBuilder { waker, local_waker } = self;
346-
Context { waker, local_waker, _marker: PhantomData, _marker2: PhantomData }
347-
}
348-
}
349-
350-
/// Construct a [`ContextBuilder`] from a [`Context`]. This is useful for
351-
/// overriding values from a context.
352-
///
353-
/// # Examples
354-
/// An example of a future that allows to set a [`Waker`] on Context if none was defined.
355-
/// This can be used to await futures that require a [`Waker`] even if the runtime does not
356-
/// support [`Waker`].
357-
/// ```rust
358-
/// #![feature(noop_waker, local_waker)]
359-
/// use std::task::{Waker, ContextBuilder};
360-
/// use std::future::{poll_fn, Future};
361-
/// use std::pin::pin;
362-
///
363-
/// async fn with_waker<F>(f: F, waker: &Waker) -> F::Output
364-
/// where
365-
/// F: Future
366-
/// {
367-
/// let mut f = pin!(f);
368-
/// poll_fn(move |cx| {
369-
/// let has_waker = cx.try_waker().is_some();
370-
/// if has_waker {
371-
/// return f.as_mut().poll(cx);
372-
/// }
373-
///
374-
/// let mut cx = ContextBuilder::from(cx)
375-
/// .waker(&waker)
376-
/// .build();
377-
/// f.as_mut().poll(&mut cx)
378-
/// }).await
379-
/// }
380-
///
381-
/// # async fn __() {
382-
/// with_waker(async { /* ... */ }, &Waker::noop()).await;
383-
/// # }
384-
/// ```
385-
#[unstable(feature = "local_waker", issue = "118959")]
386-
impl<'a> From<&mut Context<'a>> for ContextBuilder<'a> {
387-
#[inline]
388-
fn from(value: &mut Context<'a>) -> Self {
389-
let Context { waker, local_waker, _marker, _marker2 } = *value;
390-
ContextBuilder { waker, local_waker }
327+
let ContextBuilder { waker, local_waker, _marker, _marker2 } = self;
328+
Context { waker, local_waker, _marker, _marker2 }
391329
}
392330
}
393331

@@ -600,8 +538,7 @@ impl fmt::Debug for Waker {
600538
/// Implements [`Clone`], but neither [`Send`] nor [`Sync`]; therefore, a local waker may
601539
/// not be moved to other threads. In general, when deciding to use wakers or local wakers,
602540
/// local wakers are preferable unless the waker needs to be sent across threads. This is because
603-
/// wakers can incur in additional cost related to memory synchronization, and not all executors
604-
/// may support wakers.
541+
/// wakers can incur in additional cost related to memory synchronization.
605542
///
606543
/// Note that it is preferable to use `local_waker.clone_from(&new_waker)` instead
607544
/// of `*local_waker = new_waker.clone()`, as the former will avoid cloning the waker
@@ -738,7 +675,7 @@ impl LocalWaker {
738675
/// use std::future::Future;
739676
/// use std::task::{ContextBuilder, LocalWaker};
740677
///
741-
/// let mut cx = task::ContextBuilder::new()
678+
/// let mut cx = task::ContextBuilder::from_waker(Waker::noop())
742679
/// .local_waker(LocalWaker::noop())
743680
/// .build();
744681
///

0 commit comments

Comments
 (0)