Skip to content

Commit 84804c3

Browse files
committed
Auto merge of #51814 - MajorBreakfast:local-task-obj, r=cramertj
Add `LocalTaskObj` to `core::task` - Splits `libcore/task.rs` into submodules - Adds `LocalTaskObj` and `SpawnLocalObjError` (-> [Commit for this](433e6b3)) Note: To make reviewing easy, both actions have their own commit r? @cramertj
2 parents 9cc3d44 + b39ea1d commit 84804c3

File tree

7 files changed

+455
-296
lines changed

7 files changed

+455
-296
lines changed

src/liballoc/boxed.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use core::marker::{Unpin, Unsize};
6666
use core::mem::{self, PinMut};
6767
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
6868
use core::ptr::{self, NonNull, Unique};
69-
use core::task::{Context, Poll, UnsafeTask, TaskObj};
69+
use core::task::{Context, Poll, UnsafeTask, TaskObj, LocalTaskObj};
7070
use core::convert::From;
7171

7272
use raw_vec::RawVec;
@@ -933,7 +933,7 @@ impl<'a, F: ?Sized + Future> Future for PinBox<F> {
933933
}
934934

935935
#[unstable(feature = "futures_api", issue = "50547")]
936-
unsafe impl<F: Future<Output = ()> + Send + 'static> UnsafeTask for PinBox<F> {
936+
unsafe impl<F: Future<Output = ()> + 'static> UnsafeTask for PinBox<F> {
937937
fn into_raw(self) -> *mut () {
938938
PinBox::into_raw(self) as *mut ()
939939
}
@@ -962,3 +962,17 @@ impl<F: Future<Output = ()> + Send + 'static> From<Box<F>> for TaskObj {
962962
TaskObj::new(PinBox::from(boxed))
963963
}
964964
}
965+
966+
#[unstable(feature = "futures_api", issue = "50547")]
967+
impl<F: Future<Output = ()> + 'static> From<PinBox<F>> for LocalTaskObj {
968+
fn from(boxed: PinBox<F>) -> Self {
969+
LocalTaskObj::new(boxed)
970+
}
971+
}
972+
973+
#[unstable(feature = "futures_api", issue = "50547")]
974+
impl<F: Future<Output = ()> + 'static> From<Box<F>> for LocalTaskObj {
975+
fn from(boxed: Box<F>) -> Self {
976+
LocalTaskObj::new(PinBox::from(boxed))
977+
}
978+
}

src/libcore/task/context.rs

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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+
#![unstable(feature = "futures_api",
12+
reason = "futures in libcore are unstable",
13+
issue = "50547")]
14+
15+
use fmt;
16+
use super::{Executor, Waker, LocalWaker};
17+
18+
/// Information about the currently-running task.
19+
///
20+
/// Contexts are always tied to the stack, since they are set up specifically
21+
/// when performing a single `poll` step on a task.
22+
pub struct Context<'a> {
23+
local_waker: &'a LocalWaker,
24+
executor: &'a mut Executor,
25+
}
26+
27+
impl<'a> fmt::Debug for Context<'a> {
28+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29+
f.debug_struct("Context")
30+
.finish()
31+
}
32+
}
33+
34+
impl<'a> Context<'a> {
35+
/// Create a new task `Context` with the provided `local_waker`, `waker`, and `executor`.
36+
#[inline]
37+
pub fn new(local_waker: &'a LocalWaker, executor: &'a mut Executor) -> Context<'a> {
38+
Context {
39+
local_waker,
40+
executor,
41+
}
42+
}
43+
44+
/// Get the `LocalWaker` associated with the current task.
45+
#[inline]
46+
pub fn local_waker(&self) -> &'a LocalWaker {
47+
self.local_waker
48+
}
49+
50+
/// Get the `Waker` associated with the current task.
51+
#[inline]
52+
pub fn waker(&self) -> &'a Waker {
53+
unsafe { &*(self.local_waker as *const LocalWaker as *const Waker) }
54+
}
55+
56+
/// Get the default executor associated with this task.
57+
///
58+
/// This method is useful primarily if you want to explicitly handle
59+
/// spawn failures.
60+
#[inline]
61+
pub fn executor(&mut self) -> &mut Executor {
62+
self.executor
63+
}
64+
65+
/// Produce a context like the current one, but using the given waker instead.
66+
///
67+
/// This advanced method is primarily used when building "internal
68+
/// schedulers" within a task, where you want to provide some customized
69+
/// wakeup logic.
70+
#[inline]
71+
pub fn with_waker<'b>(&'b mut self, local_waker: &'b LocalWaker) -> Context<'b> {
72+
Context {
73+
local_waker,
74+
executor: self.executor,
75+
}
76+
}
77+
78+
/// Produce a context like the current one, but using the given executor
79+
/// instead.
80+
///
81+
/// This advanced method is primarily used when building "internal
82+
/// schedulers" within a task.
83+
#[inline]
84+
pub fn with_executor<'b, E>(&'b mut self, executor: &'b mut E) -> Context<'b>
85+
where E: Executor
86+
{
87+
Context {
88+
local_waker: self.local_waker,
89+
executor: executor,
90+
}
91+
}
92+
}

src/libcore/task/executor.rs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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+
#![unstable(feature = "futures_api",
12+
reason = "futures in libcore are unstable",
13+
issue = "50547")]
14+
15+
use fmt;
16+
use super::{TaskObj, LocalTaskObj};
17+
18+
/// A task executor.
19+
///
20+
/// A *task* is a `()`-producing async value that runs at the top level, and will
21+
/// be `poll`ed until completion. It's also the unit at which wake-up
22+
/// notifications occur. Executors, such as thread pools, allow tasks to be
23+
/// spawned and are responsible for putting tasks onto ready queues when
24+
/// they are woken up, and polling them when they are ready.
25+
pub trait Executor {
26+
/// Spawn the given task, polling it until completion.
27+
///
28+
/// # Errors
29+
///
30+
/// The executor may be unable to spawn tasks, either because it has
31+
/// been shut down or is resource-constrained.
32+
fn spawn_obj(&mut self, task: TaskObj) -> Result<(), SpawnObjError>;
33+
34+
/// Determine whether the executor is able to spawn new tasks.
35+
///
36+
/// # Returns
37+
///
38+
/// An `Ok` return means the executor is *likely* (but not guaranteed)
39+
/// to accept a subsequent spawn attempt. Likewise, an `Err` return
40+
/// means that `spawn` is likely, but not guaranteed, to yield an error.
41+
#[inline]
42+
fn status(&self) -> Result<(), SpawnErrorKind> {
43+
Ok(())
44+
}
45+
}
46+
47+
/// Provides the reason that an executor was unable to spawn.
48+
pub struct SpawnErrorKind {
49+
_hidden: (),
50+
}
51+
52+
impl fmt::Debug for SpawnErrorKind {
53+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54+
f.debug_tuple("SpawnErrorKind")
55+
.field(&"shutdown")
56+
.finish()
57+
}
58+
}
59+
60+
impl SpawnErrorKind {
61+
/// Spawning is failing because the executor has been shut down.
62+
pub fn shutdown() -> SpawnErrorKind {
63+
SpawnErrorKind { _hidden: () }
64+
}
65+
66+
/// Check whether this error is the `shutdown` error.
67+
pub fn is_shutdown(&self) -> bool {
68+
true
69+
}
70+
}
71+
72+
/// The result of a failed spawn
73+
#[derive(Debug)]
74+
pub struct SpawnObjError {
75+
/// The kind of error
76+
pub kind: SpawnErrorKind,
77+
78+
/// The task for which spawning was attempted
79+
pub task: TaskObj,
80+
}
81+
82+
/// The result of a failed spawn
83+
#[derive(Debug)]
84+
pub struct SpawnLocalObjError {
85+
/// The kind of error
86+
pub kind: SpawnErrorKind,
87+
88+
/// The task for which spawning was attempted
89+
pub task: LocalTaskObj,
90+
}

src/libcore/task/mod.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
#![unstable(feature = "futures_api",
12+
reason = "futures in libcore are unstable",
13+
issue = "50547")]
14+
15+
//! Types and Traits for working with asynchronous tasks.
16+
17+
mod context;
18+
pub use self::context::Context;
19+
20+
mod executor;
21+
pub use self::executor::{
22+
Executor, SpawnErrorKind, SpawnObjError, SpawnLocalObjError
23+
};
24+
25+
mod poll;
26+
pub use self::poll::Poll;
27+
28+
mod task;
29+
pub use self::task::{TaskObj, LocalTaskObj, UnsafeTask};
30+
31+
mod wake;
32+
pub use self::wake::{Waker, LocalWaker, UnsafeWake};

src/libcore/task/poll.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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+
#![unstable(feature = "futures_api",
12+
reason = "futures in libcore are unstable",
13+
issue = "50547")]
14+
15+
/// Indicates whether a value is available or if the current task has been
16+
/// scheduled to receive a wakeup instead.
17+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
18+
pub enum Poll<T> {
19+
/// Represents that a value is immediately ready.
20+
Ready(T),
21+
22+
/// Represents that a value is not ready yet.
23+
///
24+
/// When a function returns `Pending`, the function *must* also
25+
/// ensure that the current task is scheduled to be awoken when
26+
/// progress can be made.
27+
Pending,
28+
}
29+
30+
impl<T> Poll<T> {
31+
/// Change the ready value of this `Poll` with the closure provided
32+
pub fn map<U, F>(self, f: F) -> Poll<U>
33+
where F: FnOnce(T) -> U
34+
{
35+
match self {
36+
Poll::Ready(t) => Poll::Ready(f(t)),
37+
Poll::Pending => Poll::Pending,
38+
}
39+
}
40+
41+
/// Returns whether this is `Poll::Ready`
42+
pub fn is_ready(&self) -> bool {
43+
match *self {
44+
Poll::Ready(_) => true,
45+
Poll::Pending => false,
46+
}
47+
}
48+
49+
/// Returns whether this is `Poll::Pending`
50+
pub fn is_pending(&self) -> bool {
51+
!self.is_ready()
52+
}
53+
}
54+
55+
impl<T, E> Poll<Result<T, E>> {
56+
/// Change the success value of this `Poll` with the closure provided
57+
pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
58+
where F: FnOnce(T) -> U
59+
{
60+
match self {
61+
Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
62+
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
63+
Poll::Pending => Poll::Pending,
64+
}
65+
}
66+
67+
/// Change the error value of this `Poll` with the closure provided
68+
pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
69+
where F: FnOnce(E) -> U
70+
{
71+
match self {
72+
Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
73+
Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
74+
Poll::Pending => Poll::Pending,
75+
}
76+
}
77+
}
78+
79+
impl<T> From<T> for Poll<T> {
80+
fn from(t: T) -> Poll<T> {
81+
Poll::Ready(t)
82+
}
83+
}

0 commit comments

Comments
 (0)