Skip to content

Commit

Permalink
Add spawn() public function to pass raw futures through to the execut…
Browse files Browse the repository at this point in the history
…or (bevyengine#1)

Add a task newtype so that we don't expose multitask::Task
Remove some of the README/license info that was present in the prototype repo
Add some doc comments
  • Loading branch information
aclysma committed Aug 29, 2020
1 parent d538b09 commit a6eb14b
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 258 deletions.
3 changes: 0 additions & 3 deletions crates/bevy_tasks/.gitignore

This file was deleted.

1 change: 1 addition & 0 deletions crates/bevy_tasks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "bevy_tasks"
version = "0.1.0"
authors = [
"Bevy Contributors <[email protected]>",
"Lachlan Sneff <[email protected]>",
"Philip Degarmo <[email protected]>"
]
Expand Down
201 changes: 0 additions & 201 deletions crates/bevy_tasks/LICENSE-APACHE

This file was deleted.

23 changes: 0 additions & 23 deletions crates/bevy_tasks/LICENSE-MIT

This file was deleted.

26 changes: 3 additions & 23 deletions crates/bevy_tasks/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# bevy_tasks

A refreshingly simple task executor for bevy. :)

This is a simple threadpool with minimal dependencies. The main usecase is a scoped fork-join, i.e. spawning tasks from
a single thread and having that thread await the completion of those tasks. This is intended specifically for
[`bevy`][bevy] as a lighter alternative to [`rayon`][rayon] for this specific usecase. There are also utilities for
Expand All @@ -15,7 +17,7 @@ It is based on [`multitask`][multitask], a lightweight executor that allows the

## Dependencies

A very small dependency list is a key feature of this library
A very small dependency list is a key feature of this module

```
├── multitask
Expand All @@ -28,25 +30,3 @@ A very small dependency list is a key feature of this library
├── parking
└── pollster
```

## Status

This is an unpublished prototype intended for eventual inclusion with `bevy`.

## License

Licensed under either of

* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT).
39 changes: 31 additions & 8 deletions crates/bevy_tasks/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use multitask::{Executor, Task};
use parking::Unparker;
use std::{
fmt::{self, Debug},
Expand All @@ -16,6 +15,9 @@ use std::{
mod slice;
pub use slice::{ParallelSlice, ParallelSliceMut};

mod task;
pub use task::Task;

macro_rules! pin_mut {
($($x:ident),*) => { $(
// Move the value to ensure that it is owned
Expand Down Expand Up @@ -91,14 +93,16 @@ impl TaskPoolBuilder {
}
}

/// A thread pool for executing tasks. Tasks are futures that are being automatically driven by
/// the pool on threads owned by the pool.
pub struct TaskPool {
executor: Arc<Executor>,
executor: Arc<multitask::Executor>,
threads: Vec<(JoinHandle<()>, Arc<Unparker>)>,
shutdown_flag: Arc<AtomicBool>,
}

impl TaskPool {
// Create a `TaskPool` with the default configuration.
/// Create a `TaskPool` with the default configuration.
pub fn new() -> TaskPool {
TaskPoolBuilder::new().build()
}
Expand All @@ -125,7 +129,7 @@ impl TaskPool {
stack_size: Option<usize>,
thread_name: Option<&str>,
) -> Self {
let executor = Arc::new(Executor::new());
let executor = Arc::new(multitask::Executor::new());
let shutdown_flag = Arc::new(AtomicBool::new(false));

let num_threads = num_threads.unwrap_or_else(num_cpus::get);
Expand Down Expand Up @@ -177,17 +181,22 @@ impl TaskPool {
}
}

/// Return the number of threads owned by the task pool
pub fn thread_num(&self) -> usize {
self.threads.len()
}

/// Allows spawning non-`static futures on the thread pool. The function takes a callback,
/// passing a scope object into it. The scope object provided to the callback can be used
/// to spawn tasks. This function will await the completion of all tasks before returning.
///
/// This is similar to `rayon::scope` and `crossbeam::scope`
pub fn scope<'scope, F, T>(&self, f: F) -> Vec<T>
where
F: FnOnce(&mut Scope<'scope, T>) + 'scope + Send,
T: Send + 'static,
{
// let ex = Arc::clone(&self.executor);
let executor: &'scope Executor = unsafe { mem::transmute(&*self.executor) };
let executor: &'scope multitask::Executor = unsafe { mem::transmute(&*self.executor) };

let fut = async move {
let mut scope = Scope {
Expand All @@ -214,6 +223,20 @@ impl TaskPool {
pollster::block_on(self.executor.spawn(fut))
}

/// Spawns a static future onto the thread pool. The returned Task is a future. It can also be
/// cancelled and "detached" allowing it to continue running without having to be polled by the
/// end-user.
pub fn spawn<T>(
&self,
future: impl Future<Output = T> + Send + 'static,
) -> impl Future<Output = T> + Send
where
T: Send + 'static,
{
self.executor.spawn(future)
}

/// Joins all the threads in the thread pool.
pub fn shutdown(self) -> Result<(), ThreadPanicked> {
let mut this = self;
this.shutdown_internal()
Expand Down Expand Up @@ -256,8 +279,8 @@ impl Debug for ThreadPanicked {
}

pub struct Scope<'scope, T> {
executor: &'scope Executor,
spawned: Vec<Task<T>>,
executor: &'scope multitask::Executor,
spawned: Vec<multitask::Task<T>>,
}

impl<'scope, T: Send + 'static> Scope<'scope, T> {
Expand Down
Loading

0 comments on commit a6eb14b

Please sign in to comment.