shred/lib.rs
1#![cfg_attr(feature = "nightly", feature(ptr_metadata, strict_provenance))]
2//! **Sh**ared **re**source **d**ispatcher
3//!
4//! This library allows to dispatch
5//! systems, which can have interdependencies,
6//! shared and exclusive resource access, in parallel.
7//!
8//! # Examples
9//!
10//! ```rust
11//! extern crate shred;
12//!
13//! use shred::{DispatcherBuilder, Read, Resource, ResourceId, System, SystemData, World, Write};
14//!
15//! #[derive(Debug, Default)]
16//! struct ResA;
17//!
18//! #[derive(Debug, Default)]
19//! struct ResB;
20//!
21//! # #[cfg(feature = "shred-derive")]
22//! #[derive(SystemData)] // Provided with `shred-derive` feature
23//! struct Data<'a> {
24//! a: Read<'a, ResA>,
25//! b: Write<'a, ResB>,
26//! }
27//!
28//! struct EmptySystem;
29//!
30//! impl<'a> System<'a> for EmptySystem {
31//! type SystemData = Data<'a>;
32//!
33//! fn run(&mut self, bundle: Data<'a>) {
34//! println!("{:?}", &*bundle.a);
35//! println!("{:?}", &*bundle.b);
36//! }
37//! }
38//!
39//! let mut world = World::empty();
40//! let mut dispatcher = DispatcherBuilder::new()
41//! .with(EmptySystem, "empty", &[])
42//! .build();
43//! world.insert(ResA);
44//! world.insert(ResB);
45//!
46//! dispatcher.dispatch(&mut world);
47//! #
48//! # // The following is required for the snippet to compile without the `shred-derive` feature.
49//! #
50//! # #[cfg(not(feature = "shred-derive"))]
51//! # struct Data<'a> {
52//! # a: Read<'a, ResA>,
53//! # b: Write<'a, ResB>,
54//! # }
55//! #
56//! # #[cfg(not(feature = "shred-derive"))]
57//! # impl<'a> SystemData<'a> for Data<'a> {
58//! # fn setup(world: &mut World) {
59//! # Read::<'_, ResA>::setup(world);
60//! # Write::<'_, ResB>::setup(world);
61//! # }
62//! #
63//! # fn fetch(world: &'a World) -> Self {
64//! # Self {
65//! # a: Read::<'_, ResA>::fetch(world),
66//! # b: Write::<'_, ResB>::fetch(world),
67//! # }
68//! # }
69//! #
70//! # fn reads() -> Vec<ResourceId> {
71//! # Read::<'_, ResA>::reads()
72//! # }
73//! #
74//! # fn writes() -> Vec<ResourceId> {
75//! # Write::<'_, ResB>::writes()
76//! # }
77//! # }
78//! ```
79//!
80//! Once you are more familiar with how system data and parallelization works,
81//! you can take look at a more flexible and performant way to dispatch:
82//! `ParSeq`. Using it is bit trickier, but it allows dispatching without any
83//! virtual function calls.
84
85#![deny(unused_must_use, clippy::disallowed_types)]
86#![deny(unsafe_op_in_unsafe_fn)]
87#![warn(missing_docs)]
88
89/// Re-exports from [`atomic_refcell`]
90///
91/// Mainly for internals, most users don't need to interact with this.
92pub mod cell {
93 pub use atomic_refcell::*;
94}
95
96mod dispatch;
97mod meta;
98mod system;
99mod world;
100
101/// A reexport of the `#[derive(SystemData]` macro provided by `shred-derive`.
102/// This requires that the `shred-derive` feature is enabled.
103#[cfg(feature = "shred-derive")]
104pub use shred_derive::SystemData;
105
106#[cfg(feature = "parallel")]
107pub use crate::dispatch::AsyncDispatcher;
108#[cfg(feature = "parallel")]
109pub use crate::dispatch::{Par, ParSeq, RunWithPool, Seq};
110pub use crate::{
111 dispatch::{
112 BatchAccessor, BatchController, BatchUncheckedWorld, Dispatcher, DispatcherBuilder,
113 MultiDispatchController, MultiDispatcher, SendDispatcher,
114 },
115 meta::{CastFrom, MetaIter, MetaIterMut, MetaTable},
116 system::{
117 Accessor, AccessorCow, DynamicSystemData, RunNow, RunningTime, StaticAccessor, System,
118 SystemData,
119 },
120 world::{
121 DefaultProvider, Entry, Fetch, FetchMut, PanicHandler, Read, ReadExpect, Resource,
122 ResourceId, SetupHandler, World, Write, WriteExpect,
123 },
124};
125
126/// Alias for `World` for easier migration to the new version. Will be removed
127/// in the future.
128#[deprecated(since = "0.8.0", note = "renamed to `World`")]
129pub type Resources = World;