]> git.proxmox.com Git - rustc.git/blame - src/libstd/future.rs
New upstream version 1.30.0+dfsg1
[rustc.git] / src / libstd / future.rs
CommitLineData
8faf50e0
XL
1// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! Asynchronous values.
12
13use core::cell::Cell;
14use core::marker::Unpin;
b7449926 15use core::pin::PinMut;
8faf50e0
XL
16use core::option::Option;
17use core::ptr::NonNull;
18use core::task::{self, Poll};
19use core::ops::{Drop, Generator, GeneratorState};
20
21#[doc(inline)]
22pub use core::future::*;
23
24/// Wrap a future in a generator.
25///
26/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
27/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
28#[unstable(feature = "gen_future", issue = "50547")]
29pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
30 GenFuture(x)
31}
32
33/// A wrapper around generators used to implement `Future` for `async`/`await` code.
34#[unstable(feature = "gen_future", issue = "50547")]
35#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
36struct GenFuture<T: Generator<Yield = ()>>(T);
37
38// We rely on the fact that async/await futures are immovable in order to create
39// self-referential borrows in the underlying generator.
40impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
41
42#[unstable(feature = "gen_future", issue = "50547")]
43impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
44 type Output = T::Return;
45 fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
46 set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } {
47 GeneratorState::Yielded(()) => Poll::Pending,
48 GeneratorState::Complete(x) => Poll::Ready(x),
49 })
50 }
51}
52
53thread_local! {
54 static TLS_CX: Cell<Option<NonNull<task::Context<'static>>>> = Cell::new(None);
55}
56
57struct SetOnDrop(Option<NonNull<task::Context<'static>>>);
58
59impl Drop for SetOnDrop {
60 fn drop(&mut self) {
61 TLS_CX.with(|tls_cx| {
62 tls_cx.set(self.0.take());
63 });
64 }
65}
66
67#[unstable(feature = "gen_future", issue = "50547")]
68/// Sets the thread-local task context used by async/await futures.
69pub fn set_task_cx<F, R>(cx: &mut task::Context, f: F) -> R
70where
71 F: FnOnce() -> R
72{
73 let old_cx = TLS_CX.with(|tls_cx| {
74 tls_cx.replace(NonNull::new(
75 cx
76 as *mut task::Context
77 as *mut ()
78 as *mut task::Context<'static>
79 ))
80 });
81 let _reset_cx = SetOnDrop(old_cx);
82 f()
83}
84
85#[unstable(feature = "gen_future", issue = "50547")]
86/// Retrieves the thread-local task context used by async/await futures.
87///
88/// This function acquires exclusive access to the task context.
89///
90/// Panics if no task has been set or if the task context has already been
b7449926 91/// retrieved by a surrounding call to get_task_cx.
8faf50e0
XL
92pub fn get_task_cx<F, R>(f: F) -> R
93where
94 F: FnOnce(&mut task::Context) -> R
95{
96 let cx_ptr = TLS_CX.with(|tls_cx| {
97 // Clear the entry so that nested `with_get_cx` calls
98 // will fail or set their own value.
99 tls_cx.replace(None)
100 });
101 let _reset_cx = SetOnDrop(cx_ptr);
102
103 let mut cx_ptr = cx_ptr.expect(
104 "TLS task::Context not set. This is a rustc bug. \
105 Please file an issue on https://github.com/rust-lang/rust.");
106 unsafe { f(cx_ptr.as_mut()) }
107}
108
109#[unstable(feature = "gen_future", issue = "50547")]
110/// Polls a future in the current thread-local task context.
b7449926 111pub fn poll_in_task_cx<F>(f: PinMut<F>) -> Poll<F::Output>
8faf50e0
XL
112where
113 F: Future
114{
b7449926 115 get_task_cx(|cx| f.poll(cx))
8faf50e0 116}