• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H03-May-2022-7037

ci/H03-May-2022-15054

src/H03-May-2022-2,3351,244

.cargo-checksum.jsonH A D03-May-202289 11

.gitignoreH A D01-Jan-1970320 118

CHANGELOG.mdH A D01-Jan-19705.6 KiB15497

Cargo.lockH A D01-Jan-197028.6 KiB1,1611,040

Cargo.tomlH A D01-Jan-19704.6 KiB189158

Cargo.toml.orig-cargoH A D01-Jan-19704.3 KiB191154

Cargo.ymlH A D01-Jan-19707.5 KiB262186

LICENSEH A D01-Jan-19701.2 KiB2520

README.mdH A D01-Jan-197010.9 KiB265167

build.rsH A D01-Jan-1970440 1711

README.md

1# async_executors
2
3[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
4[![Build Status](https://api.travis-ci.org/najamelan/async_executors.svg?branch=master)](https://travis-ci.org/najamelan/async_executors)
5[![Docs](https://docs.rs/async_executors/badge.svg)](https://docs.rs/async_executors)
6[![crates.io](https://img.shields.io/crates/v/async_executors.svg)](https://crates.io/crates/async_executors)
7
8
9> Abstract over different executors.
10
11_async_executors_ aims to help you write executor agnostic libraries. We express common executor functionality in traits and implement it for the most used executors. This way libraries can require the exact functionality they need and client code can use any executor they choose as long as it can provide the required functionality.
12
13Available traits are grouped in the [`iface`] module. We also implement [`Spawn`](futures_util::task::Spawn) and/or [`LocalSpawn`](futures_util::task::LocalSpawn) traits from _futures_.
14
15All supported executors are turned on with features, see below.
16
17
18## Table of Contents
19
20- [Install](#install)
21   - [Upgrade](#upgrade)
22   - [Dependencies](#dependencies)
23   - [Security](#security)
24- [Features](#features)
25   - [General Features](#general-features)
26   - [Executor Specific](#executor-specific)
27- [Usage](#usage)
28   - [Basic Example](#basic-example)
29   - [API](#api)
30- [Contributing](#contributing)
31   - [Code of Conduct](#code-of-conduct)
32- [License](#license)
33
34
35## Install
36
37With [cargo add](https://github.com/killercup/cargo-edit):
38`cargo add async_executors`
39
40With [cargo yaml](https://gitlab.com/storedbox/cargo-yaml):
41```yaml
42dependencies:
43
44   async_executors: ^0.4
45```
46
47With Cargo.toml
48```toml
49[dependencies]
50
51    async_executors = "0.4"
52```
53
54### Upgrade
55
56Please check out the [changelog](https://github.com/najamelan/async_executors/blob/master/CHANGELOG.md) when upgrading.
57
58
59### Dependencies
60
61This crate has few dependencies. Cargo will automatically handle it's dependencies for you.
62
63The only hard dependencies are `futures-task` and `futures-util`. The rest are the optional dependencies to turn on support for each executor.
64
65## Features
66
67This crate has a lot of features. Lets go over them:
68
69### General features
70- `tracing`: when enabled, all traits are re-implemented for [`tracing-futures::Instrumented`] and [`tracing-futures::WithDispatch`].
71- `timer`  : Provides executor's with timer support. For executors that don't have built in timers, the _future-timer_ crate is used.
72
73### Executor specific:
74- `async_global`      : Turns on the executor from [_async-global-executor_](https://docs.rs/async-global-executor).
75   Supports Wasm, `!Send` tasks.
76- `async_global_tokio`: Makes sure a tokio reactor is running for tasks spawned on [`AsyncGlobal`].
77- `async_std`         : Turns on the executor from the [_async-std_](https://docs.rs/async-std) crate. Supports Wasm and `!Send` tasks.
78- `async_std_tokio`   : Makes sure a tokio reactor is running for tasks spawned on [`AsyncStd`].
79- `glommio`           : Turns on the executor from the [_glommio_](https://docs.rs/glommio) crate. Single threaded, Linux 5.8+ only. Supports `!Send` tasks.
80- `tokio_ct`          : Tokio Current thread, enables a single threaded runtime from the [_tokio_](https://docs.rs/tokio) crate. Supports `!Send` tasks.
81- `tokio_tp`          : Tokio threadpool, enables a threadpool runtime from the [_tokio_](https://docs.rs/tokio) crate.
82- `tokio_timer`       : Will enable the `time` feature on _tokio_ and call `enable_time()` on any tokio runtimes you create. For tokio runtimes, this takes precedence over the `timer` feature.
83- `tokio_io`          : Will enable the `net` and `process` features on _tokio_ and call `enable_reactor()` on any tokio runtimes you create.
84- `localpool`         : Enables the single threaded executor from [_futures-executor_](http://docs.rs/futures-executor). Supports `!Send` tasks. `LocalPool` and `LocalSpawner` will be re-exported from this crate and have our traits implemented.
85- `threadpool`        : Enables the treadpool executor from [_futures-executor_](http://docs.rs/futures-executor). `ThreadPool` will be re-exported from this crate and have our traits implemented.
86- `bindgen`           : Enables the single threaded executor from [_wasm-bindgen-futures_](https://docs.rs/wasm-bindgen-futures). Wasm only. Supports `!Send` tasks.
87
88
89
90## Security
91
92The crate itself uses `#[ forbid(unsafe_code) ]`.
93
94Our dependencies use unsafe.
95
96
97## Performance
98
99Most wrappers are very thin but the `Spawn` and `LocalSpawn` traits do imply boxing the future. With executors boxing futures
100to put them in a queue you probably get 2 heap allocations per spawn.
101
102`JoinHandle` uses the native `JoinHandle` types from _tokio_ and _async-std_ to avoid the overhead from `RemoteHandle`, but for _async-std_, wrap the future in `Abortable` to create consistent behavior across all executors. The `JoinHandle` provided cancels it's future on drop unless you call `detach` on it.
103
104`SpawnHandle` and `LocalSpawnHandle` require boxing the future twice, just like `Spawn` and `LocalSpawn`.
105
106Existing benchmarks for all executors can be found in [executor_benchmarks](https://github.com/najamelan/executor_benchmarks).
107
108
109## Missing features
110
111These are some features that aren't provided yet but that are on the todo list:
112
113- an agnostic interface for `spawn_blocking`.
114
115
116## Usage
117
118### For API providers
119
120When writing a library that needs to spawn, you probably shouldn't lock your clients into one framework or another. It's usually not appropriate to setup your own thread pool for spawning futures. It belongs to the application developer to decide where futures are spawned and it might not be appreciated if libraries bring in extra dependencies on a framework.
121
122In order to get round this you can take an executor in as a parameter from client code and spawn your futures on the provided executor. Currently the only two traits that are kind of widely available for this are `Spawn` and `LocalSpawn` from the _futures_ library. Unfortunately, other executor providers do not implement these traits. So by publishing an API that relies on these traits, you would have been restricting the clients to use the executors from _futures_, or start implementing their own wrappers that implement the traits.
123
124_Async_executors_ has wrappers providing impls on various executors, namely _tokio_, _async_std_, _wasm_bindgen_, ... As such you can just use the trait bounds and refer your users to this crate if they want to use any of the supported executors.
125
126All wrappers also implement `Clone`, `Debug` and the zero sized ones also `Copy`. You can express you will need to clone in your API: `impl Spawn + Clone`.
127
128Note that you should never use `block_on` inside async contexts. Depending on the executor, this might hang or panic. Some backends we use like _tokio_ and `RemoteHandle` from _futures_ use `catch_unwind`, so try to keep futures unwind safe.
129
130#### Spawning with handles
131
132You can use the `SpawnHandle` and `LocalSpawnHandle` traits as bounds for obtaining join handles.
133
134##### Example
135
136```rust, ignore
137use
138{
139  async_executors :: { JoinHandle, SpawnHandle, SpawnHandleExt       } ,
140  std             :: { sync::Arc                                     } ,
141  futures         :: { FutureExt, executor::{ ThreadPool, block_on } } ,
142};
143
144
145// Example of a library function that needs an executor. Just use impl Trait.
146//
147fn needs_exec( exec: impl SpawnHandle<()> )
148{
149   let handle = exec.spawn_handle( async {} );
150}
151
152
153// A type that needs to hold on to an executor during it's lifetime. Here it
154// must be heap allocated.
155//
156struct SomeObj{ exec: Arc< dyn SpawnHandle<u8> > }
157
158
159impl SomeObj
160{
161   pub fn new( exec: Arc< dyn SpawnHandle<u8> > ) -> SomeObj
162   {
163      SomeObj{ exec }
164   }
165
166   fn run( &self ) -> JoinHandle<u8>
167   {
168      self.exec.spawn_handle( async{ 5 } ).expect( "spawn" )
169   }
170}
171
172
173fn main()
174{
175  let exec = ThreadPool::new().expect( "build threadpool" );
176  let obj  = SomeObj::new( Arc::new(exec) );
177
178  let x = block_on( obj.run() );
179
180  assert_eq!( x, 5 );
181}
182```
183
184As you can see from the above example, the output of the future is a type parameter on `SpawnHandle`. This is necessary because putting it on the method would make the trait no longer object safe, which means it couldn't be stored unless as a type parameter.
185
186The best way to define a combination of abilities you need is by making your own trait alias:
187
188```rust, ignore
189trait_set!
190{
191   pub trait LibExec = SpawnHandle<()> + SpawnHandle<u8> + Timer + YieldNow + Clone;
192}
193
194pub fn lib_function( exec: impl LibExec ) { ... }
195
196```
197
198All implementers of `SpawnHandle` must support any output type. Thus adding more `SpawnHandle` bounds to `LibExec` should not be a breaking change.
199
200
201### For API consumers
202
203You can basically pass the wrapper types provided in _async_executors_ to API's that take any of the following. Traits are also implemented for `Rc`, `Arc`, `&`, `&mut`, `Box` and `Instrumented` and `WithDispatch` from _tracing-futures_ wrappers:
204
205  - `impl Spawn`
206  - `impl LocalSpawn`
207  - `impl SpawnHandle<T>`
208  - `impl LocalSpawnHandle<T>`
209  - `impl YieldNow`
210  - `impl Timer`
211  - `impl TokioIo`
212
213All wrappers also implement `Clone`, `Debug` and the zero sized ones also `Copy`.
214
215Some executors are a bit special, so make sure to check the API docs for the one you intend to use. Some also provide extra methods like `block_on` which will call a framework specific `block_on` rather than the one from _futures_.
216
217#### Example
218
219```rust, ignore
220use
221{
222  async_executors :: { AsyncStd, TokioTpBuilder, SpawnHandle } ,
223  std             :: { convert::TryFrom                      } ,
224};
225
226fn needs_exec( exec: impl SpawnHandle<()> + SpawnHandle<String> ){};
227
228// AsyncStd is zero sized, so it's easy to instantiate.
229//
230needs_exec( AsyncStd );
231
232// We need a builder type for tokio, as we guarantee by the type of TokioTp that it
233// will be a threadpool.
234//
235let tp = TokioTpBuilder::new().build().expect( "build threadpool" );
236
237needs_exec( tp );
238```
239
240For more examples, check out the [examples directory](https://github.com/najamelan/async_executors/tree/master/examples). If you want to get a more polished API for adhering to structured concurrency, check out [_async_nursery_](https://crates.io/crates/async_nursery).
241
242## API
243
244API documentation can be found on [docs.rs](https://docs.rs/async_executors).
245
246
247## Contributing
248
249Please check out the [contribution guidelines](https://github.com/najamelan/async_executors/blob/master/CONTRIBUTING.md).
250
251
252### Testing
253
254Run `ci/test.bash` and `ci/wasm.bash` to run all tests.
255
256
257### Code of conduct
258
259Any of the behaviors described in [point 4 "Unacceptable Behavior" of the Citizens Code of Conduct](https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md#4-unacceptable-behavior) are not welcome here and might get you banned. If anyone including maintainers and moderators of the project fail to respect these/your limits, you are entitled to call them out.
260
261## License
262
263[Unlicence](https://unlicense.org/)
264
265