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
//! [![Latest Version]][crates.io]
//! [![Documentation]][docs.rs]
//! [![License]][license link]
//!
//! [Latest Version]: https://img.shields.io/crates/v/yaks.svg
//! [crates.io]: https://crates.io/crates/yaks
//! [Documentation]: https://docs.rs/yaks/badge.svg
//! [docs.rs]: https://docs.rs/yaks
//! [License]: https://img.shields.io/crates/l/yaks.svg
//! [license link]: https://github.com/Ratysz/yaks/blob/master/LICENSE.md
//!
//! `yaks` aims to be a minimalistic and performant framework for automatic
//! multithreading of [`hecs`] via [`rayon`].
//!
//! The goals are, in no particular order:
//! - safety
//! - simplicity
//! - performance
//! - extensibility
//! - tight engineering
//! - minimal dependencies
//! - effortless concurrency
//!
//! [`hecs`]: https://crates.io/crates/hecs
//! [`rayon`]: https://crates.io/crates/rayon
//!
//! # Cargo features
//!
//! - `parallel` - enabled by default; can be disabled to force `yaks` to work on a single thread.
//! Useful for writing the code once, and running it on platforms with or without threading.
//! - `test` - if enabled, turns off an internal drop check. Useful to prevent panic while
//! panicking when automatically testing panic conditions.
//!
//! # Example
//!
//! A more elaborate and annotated example can be found
//! [here](https://github.com/Ratysz/yaks/blob/0.1.0/examples/convoluted.rs).
//!
//! ```rust
//! use hecs::{With, Without, World};
//! use yaks::{Executor, QueryMarker};
//!
//! let mut world = World::new();
//! let mut entities = 0u32;
//! world.spawn_batch((0..100u32).map(|index| {
//! entities += 1;
//! (index,)
//! }));
//! world.spawn_batch((0..100u32).map(|index| {
//! entities += 1;
//! (index, index as f32)
//! }));
//! let mut increment = 5usize;
//! let mut average = 0f32;
//! let mut executor = Executor::<(u32, usize, f32)>::builder()
//! .system_with_handle(
//! |context, (entities, average): (&u32, &mut f32), query: QueryMarker<&f32>| {
//! *average = 0.0;
//! for (_entity, float) in context.query(query).iter() {
//! *average += *float;
//! }
//! *average /= *entities as f32;
//! },
//! "average",
//! )
//! .system_with_handle(
//! |context, increment: &usize, query: QueryMarker<&mut u32>| {
//! for (_entity, unsigned) in context.query(query).iter() {
//! *unsigned += *increment as u32
//! }
//! },
//! "increment",
//! )
//! .system_with_deps(system_with_two_queries, vec!["increment", "average"])
//! .build();
//! executor.run(&world, (&mut entities, &mut increment, &mut average));
//!
//! fn system_with_two_queries(
//! context: yaks::SystemContext,
//! (entities, average): (&u32, &f32),
//! (with_f32, without_f32): (
//! QueryMarker<With<f32, &mut u32>>,
//! QueryMarker<Without<f32, &mut u32>>,
//! ),
//! ) {
//! yaks::batch(&mut context.query(with_f32), entities / 8, |_, unsigned| {
//! *unsigned += average.round() as u32;
//! });
//! yaks::batch(
//! &mut context.query(without_f32),
//! entities / 8,
//! |_entity, unsigned| {
//! *unsigned *= average.round() as u32;
//! },
//! );
//! }
//! ```
use ;
use AtomicBorrow;
use Contains;
use DerefTuple;
use SystemClosure;
use ;
use ExecutorParallel;
use Fetch;
use QueryBundle;
use ;
use ;
pub use batch;
pub use Executor;
pub use ExecutorBuilder;
pub use QueryMarker;
pub use SystemContext;