1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
//! # async_runtime
//!
//! [![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
//! [![Build Status](https://api.travis-ci.org/najamelan/async_runtime.svg?branch=master)](https://travis-ci.org/najamelan/async_runtime)
//! [![Docs](https://docs.rs/naja_async_runtime/badge.svg)](https://docs.rs/naja_async_runtime)
//! ![crates.io](https://img.shields.io/crates/v/naja_async_runtime.svg)
//!
//!
//! > A lightweight runtime for global spawning of futures.
//!
//! The purpose of `async_runtime` is to make it convenient to spawn and run futures.
//! It allows library authors to call [`rt::spawn( future );`](rt::spawn) rather than having to take a `T: Executor`,
//! yet let client code decide what kind of executor is used. Currently the choice is between
//! futures 0.3 `LocalPool` and the [juliex](https://github.com/withoutboats/juliex) threadpool.
//! Other implementations might be added later.
//!
//! Differences with the [runtime](https://github.com/rustasync/runtime) crate:
//!
//!   - no need to box futures to spawn them, but you can spawn boxed futures just the same
//!   - client code can decide that the executor for the thread is a LocalPool (can be a serious performance benefit sometimes)
//!   - the executor is not a trait object, so you can't just implement a different one without
//!   patching this crate. I have not yet found the use for this, and tokio futures and streams
//!   run just fine with the compatibility layer from futures 0.3. If the provided executors are
//!   not sufficient, please file an issue or a pull request.
//!
//! Both crates work on WASM.
//!
//! When not on WASM, the default executor is the juliex threadpool (unless you use `default-features = false`).
//! This is because the executor is set per thread and when tasks run on a threadpool thread and they spawn,
//! they will automatically spawn on the threadpool. This alleviates the need for initialization code on the threadpool
//! threads. This means that you have to call [`rt::init`] if you want the `LocalPool` (or disable the default features).
//!
//! On WASM, the default executor is also a threadpool, even though that's impossible (wasm does not have threads right now).
//! It's recommended to use `default-features = false` on wasm to disable the dependency on juliex.
//! This will change the default executor to be the local pool. This might seem like an odd API design,
//! but WASM will have threads in the future, so I prefered keeping the API future proof and consistent with other targets.
//! Another consistency choice is that `spawn` and `spawn_local` return Result, even though currently on wasm
//! they cannot fail.
//!
//! There isn't currently a separate api documentation for WASM and docs.rs will not show modules included only
//! when the target is WASM. However, the use of the library is identical, so I have chosen not to set up a separate
//! documentation. You can check the wasm example in the
//! [examples directory of the repository](https://github.com/najamelan/async_runtime/tree/master/examples), as
//! well as the integration tests. You can also clone the repository and run:
//! `cargo doc --open --target wasm32-unknown-unknown` or read the source code.
//!
//!
//! ## Table of Contents
//!
//! - [Install](#install)
//!   - [Features](#features)
//!   - [Dependencies](#dependencies)
//! - [Usage](#usage)
//!   - [WASM](#wasm)
//! - [API](#api)
//! - [Contributing](#contributing)
//!   - [Code of Conduct](#code-of-conduct)
//! - [License](#license)
//!
//!
//! ## Install
//! With [cargo add](https://github.com/killercup/cargo-edit):
//! `cargo add async_runtime`
//!
//! With [cargo yaml](https://gitlab.com/storedbox/cargo-yaml):
//! ```yaml
//! dependencies:
//!
//!     async_runtime: { version: ^0.1, package: naja_async_runtime }
//! ```
//!
//! With raw Cargo.toml
//! ```toml
//! [dependencies]
//!
//!    async_runtime = { version = "^0.1", package = "naja_async_runtime" }
//! ```
//!
//! ### Features
//!
//! There is one feature: `juliex`. It's on by default and you can turn it off if you only want the localpool. On wasm, turn it off as it's not being used. See the [Dependencies section](#dependencies).
//!
//! ### Dependencies
//!
//! This crate has few dependiencies. Cargo will automatically handle it's dependencies for you, except:
//!
//! - `juliex` is optional. Add the dependency with `default-features = false` to disable. On wasm you should also
//!   do this as it won't be used:
//!
//!   ```toml
//!   [dependencies]
//!
//!      async_runtime = { version = "^0.1", default-features = false, package = "naja_async_runtime" }
//!   ```
//!
//! Other dependencies:
//!
//! ```yaml
//! failure         : ^0.1
//! futures-preview : { version: ^0.3.0-alpha.16, features: [ std, compat, nightly ], default-features: false }
//! log             : ^0.4
//! once_cell       : ^0.1
//! juliex          : { version: 0.3.0-alpha.6, optional: true }
//! ```
//!
//! ## Usage
//!
//! Please have a look in the [examples directory of the repository](https://github.com/najamelan/async_runtime/tree/master/examples).
//!
//! ```rust
//! # #![ feature( async_await ) ]
//! #
//! # // unfortunately we can't rename the crate itself in Cargo.yml.
//! # //
//! # use naja_async_runtime as async_runtime;
//! #
//! use
//! {
//! 	async_runtime :: { * } ,
//! };
//!
//! // in library code:
//! //
//! fn do_something_in_parallel() -> Result<(), RtErr>
//! {
//! 	rt::spawn( async
//! 	{
//! 		println!( "I'm running in async context" );
//! 	})
//! }
//!
//! // In client code we might decide that this runs in a LocalPool, instead of a threadpool:
//! //
//! fn main()
//! {
//! 	// This only fails if you initialize twice. Therefor library code should not do this
//! 	// unless the library is creating the threads.
//! 	//
//! 	rt::init( RtConfig::Local ).expect( "executor init" );
//!
//! 	// Please look at the documentation for rt::spawn for the possible errors here.
//! 	//
//! 	do_something_in_parallel().expect( "Spawn futures" );
//!
//! 	// On a threadpool, futures are polled immediately, but since here we only have one thread,
//! 	// first we spawn our topmost tasks and then we have to tell the runtime that it's time to
//! 	// start polling them. This will block the thread until all futures are finished.
//! 	//
//! 	rt::run();
//! }
//!
//! ```
//!
//! ```rust
//! // In this example we run a bunch of tasks in parallel. To verify that
//! // they run on different threads we make them all sleep for a second and
//! // measure the time passed when they finish.
//!
//! #![ feature( async_await, duration_constants ) ]
//!
//! # // unfortunately we can't rename the crate itself in Cargo.yml.
//! # //
//! # use naja_async_runtime as async_runtime;
//! #
//! use
//! {
//! 	async_runtime :: { *                                          } ,
//! 	std           :: { time::{ Duration, Instant }, thread::sleep } ,
//! 	futures       :: { future::{ FutureExt, join_all }            } ,
//! };
//!
//! fn main()
//! {
//! 	let program = async
//! 	{
//! 		let start = Instant::now();
//! 		let mut tasks = Vec::new();
//!
//! 		for i in 0..8
//! 		{
//! 			// There isn't currently a convenient way to run tasks on a threadpool
//! 			// until all tasks have finished, or until some shutdown signal is given.
//! 			//
//! 			// This is one of the ways tasks can synchronize and wait on each other.
//! 			// Another way is to wait on channels.
//! 			//
//! 			let (fut, handle) = async move
//! 			{
//! 				sleep( Duration::SECOND );
//!
//! 				println!
//! 				(
//! 					"Time elapsed at task {} end: {} second(s).",
//! 					i, start.elapsed().as_secs()
//! 				);
//!
//! 			}.remote_handle();
//!
//!
//! 			// If the juliex feature is enabled, RtConfig::Pool becomes the default executor, so we don't
//! 			// have to call rt::init.
//! 			//
//! 			rt::spawn( fut ).expect( "spawn task" );
//! 			tasks.push( handle );
//! 		}
//!
//! 		join_all( tasks ).await;
//! 	};
//!
//! 	futures::executor::block_on( program );
//! }
//! ```
//!
//! ### Wasm
//!
//! Note that it's best to turn of default-features in your Cargo.toml to avoid loading `juliex`
//!  which isn't used on wasm.
//! ```toml
//! [dependencies]
//!
//!    async_runtime = { version = "^0.1", default-features = false, package = "naja_async_runtime" }
//! ```
//!
//! To use the crate in wasm, please have a look at the example in the examples directory of the
//! [repository](https://github.com/najamelan/async_runtime).
//!
//! For the documentation, docs.rs does not make the wasm specific parts available, but their use
//! is identical to the `rt` module for other targets. The only difference is that even though it's
//! on a local pool (wasm does not have threads), you don't need to call run because the browser
//! automatically runs the promises. This might change in the future.
//!
//! For running the integration tests:
//! ```bash
//! cargo install wasm-pack wasm-bindgen-cli
//! ```
//! Now you can do either:
//! ```bash
//! wasm-pack test --firefox --headless
//! ```
//! or:
//! ```bash
//! cargo test --target wasm32-unknown-unknown
//! ```
//!
//! ## API
//!
//! Api documentation can be found on [docs.rs](https://docs.rs/async_runtime).
//!
//!
//! ## Contributing
//!
//! This repository accepts contributions. Ideas, questions, feature requests and bug reports can be filed through github issues.
//!
//! Pull Requests are welcome on github. By commiting pull requests, you accept that your code might be modified and reformatted to fit the project coding style or to improve the implementation. Please discuss what you want to see modified before filing a pull request if you don't want to be doing work that might be rejected.
//!
//!
//! ### Code of conduct
//!
//! Any of the behaviors described in [point 4 "Unacceptable Behavior" of the Citizens Code of Conduct](http://citizencodeofconduct.org/#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.
//!
//! ## License
//!
//! [Unlicence](https://unlicense.org/)
//
#![ feature( async_await ) ]

#![forbid( unsafe_code ) ]

#![ warn
(
	missing_debug_implementations ,
	missing_docs                  ,
	nonstandard_style             ,
	rust_2018_idioms              ,
)]

#![allow( clippy::suspicious_else_formatting ) ]


#[ cfg(not( target_arch = "wasm32" )) ] pub mod rt                                       ;
#[ cfg(not( target_arch = "wasm32" )) ] pub use { rt::exec03::* }                        ;

#[ cfg(     target_arch = "wasm32" )  ] pub mod wasm_rt                                  ;
#[ cfg(     target_arch = "wasm32" )  ] pub use { wasm_rt::wasm_exec::*, wasm_rt as rt } ;


mod error;
mod rt_config;

pub use
{
	error     :: * ,
	rt_config :: * ,
};


mod import
{
	pub use
	{
		once_cell :: { unsync::OnceCell, unsync::Lazy, unsync_lazy          } ,
		failure   :: { Backtrace, Fail, Context as FailContext              } ,
		std       :: { fmt, future::Future, rc::Rc, cell::RefCell, pin::Pin } ,

		futures ::
		{
			prelude :: { Stream, Sink                                                             } ,
			channel :: { oneshot, mpsc                                                            } ,
			future  :: { FutureExt, TryFutureExt                                                  } ,
			task    :: { Spawn, SpawnExt, LocalSpawn, LocalSpawnExt, Context as TaskContext, Poll } ,
			stream  :: { StreamExt                                                                } ,
			sink    :: { SinkExt                                                                  } ,

			executor::
			{
				LocalPool    as LocalPool03    ,
				LocalSpawner as LocalSpawner03 ,
				ThreadPool   as ThreadPool03   ,
			},
		},
	};
}