futures_core/task/context.rs
1use core::fmt;
2use executor::Executor;
3use task::{Waker, LocalMap};
4
5/// Information about the currently-running task.
6///
7/// Contexts are always tied to the stack, since they are set up specifically
8/// when performing a single `poll` step on a task.
9pub struct Context<'a> {
10 waker: &'a Waker,
11 pub(crate) map: &'a mut LocalMap,
12 executor: Option<&'a mut Executor>,
13}
14
15impl<'a> Context<'a> {
16 /// Create a new task context without the ability to `spawn`.
17 ///
18 /// This constructor should *only* be used for `no_std` contexts, where the
19 /// standard `Executor` trait is not available.
20 pub fn without_spawn(map: &'a mut LocalMap, waker: &'a Waker) -> Context<'a> {
21 Context { waker, map, executor: None }
22 }
23
24 /// Get the [`Waker`](::task::Waker) associated with the current task.
25 ///
26 /// The waker can subsequently be used to wake up the task when some
27 /// event of interest has happened.
28 pub fn waker(&self) -> &Waker {
29 self.waker
30 }
31
32 fn with_parts<'b, F, R>(&'b mut self, f: F) -> R
33 where F: FnOnce(&'b Waker, &'b mut LocalMap, Option<&'b mut Executor>) -> R
34 {
35 // reborrow the executor
36 let executor: Option<&'b mut Executor> = match self.executor {
37 None => None,
38 Some(ref mut e) => Some(&mut **e),
39 };
40 f(self.waker, self.map, executor)
41 }
42
43 /// Produce a context like the current one, but using the given waker
44 /// instead.
45 ///
46 /// This advanced method is primarily used when building "internal
47 /// schedulers" within a task, where you want to provide some customized
48 /// wakeup logic.
49 pub fn with_waker<'b>(&'b mut self, waker: &'b Waker) -> Context<'b> {
50 self.with_parts(|_, map, executor| {
51 Context { map, executor, waker }
52 })
53 }
54
55 /// Produce a context like the current one, but using the given task locals
56 /// instead.
57 ///
58 /// This advanced method is primarily used when building "internal
59 /// schedulers" within a task.
60 pub fn with_locals<'b>(&'b mut self, map: &'b mut LocalMap)
61 -> Context<'b>
62 {
63 self.with_parts(move |waker, _, executor| {
64 Context { map, executor, waker }
65 })
66 }
67}
68
69if_std! {
70 use std::boxed::Box;
71 use Future;
72 use never::Never;
73
74 impl<'a> Context<'a> {
75 /// Create a new task context.
76 ///
77 /// Task contexts are equipped with:
78 ///
79 /// - Task-local data
80 /// - A means of waking the task
81 /// - A means of spawning new tasks, i.e. an [executor]()
82 pub fn new(map: &'a mut LocalMap, waker: &'a Waker, executor: &'a mut Executor) -> Context<'a> {
83 Context { waker, map, executor: Some(executor) }
84 }
85
86 /// Get the default executor associated with this task, if any
87 ///
88 /// This method is useful primarily if you want to explicitly handle
89 /// spawn failures.
90 pub fn executor(&mut self) -> &mut Executor {
91 self.executor
92 .as_mut().map(|x| &mut **x)
93 .expect("No default executor found: std-using futures contexts must provide an executor")
94 }
95
96 /// Spawn a future onto the default executor.
97 ///
98 /// # Panics
99 ///
100 /// This method will panic if the default executor is unable to spawn
101 /// or does not exist.
102 ///
103 /// To handle executor errors, use [executor()](self::Context::executor)
104 /// instead.
105 pub fn spawn<F>(&mut self, f: F)
106 where F: Future<Item = (), Error = Never> + 'static + Send
107 {
108 self.executor()
109 .spawn(Box::new(f)).unwrap()
110 }
111
112 /// Produce a context like the current one, but using the given executor
113 /// instead.
114 ///
115 /// This advanced method is primarily used when building "internal
116 /// schedulers" within a task.
117 pub fn with_executor<'b>(&'b mut self, executor: &'b mut Executor)
118 -> Context<'b>
119 {
120 self.with_parts(move |waker, map, _| {
121 Context { map, executor: Some(executor), waker }
122 })
123 }
124 }
125}
126
127impl<'a> fmt::Debug for Context<'a> {
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 f.debug_struct("Context")
130 .finish()
131 }
132}