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}