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
use Debug;
/// The generic type used for a simulation's clock.
///
/// Kept generic to support as many variations of clock as possible. This trait is a superset of [`Ord`] and [`Debug`]
/// with no additional requirements or functionality.
///
/// Your implementation of this trait should use the [`Ord`] trait to account for not only the overall sequencing of
/// events, but also any tie breaking that may be necessary in your use case. Note that events will be executed in
/// ascending order of execution time, i.e. if `A.cmp(&B) == std::cmp::Ordering::Less` then event A will execute before
/// event B. Ties that you don't specify how to break will be resolved by the order in which events are enqueued, which
/// should help provide some stability in a [`serial::Simulation`]. In a [`threadsafe::Simulation`], however, this
/// tiebreaking scheme may be subject to benign race conditions, depending on how your use case takes advantage of
/// parallelization.
///
/// [`Debug`] is necessary for the implementation of [`Debug`] on both [`serial::Simulation`] and
/// [`threadsafe::Simulation`].
///
/// [`threadsafe::Simulation`] also requires that the time be both [`Send`] and [`Sync`]. [`Send`] allows for instances
/// of your implementing type to be passed to [`threadsafe::Simulation::schedule()`] from any thread, and [`Sync`]
/// permits sharing it via [`threadsafe::Simulation::current_time()`].
///
/// Implementations are provided for integral builtin types, but not for floating-point builtin types as the latter do
/// not implement [`Ord`]. If you wish to use either [`f32`] or [`f64`] as your [`SimTime`], either enable the
/// `ordered-float` feature (and so add a dependency on the [`ordered-float`] crate) to gain access to an implementation
/// on the [`OrderedFloat`] and [`NotNan`] structs, or create your own wrapper that guarantees full ordering. If you
/// intend to use [`OrderedFloat`] or [`NotNan`] with your own custom types, ensure you also implement [`Debug`] to
/// satisfy the additional requirement on `SimTime`.
///
/// [`serial::Simulation`]: crate::serial::Simulation
/// [`threadsafe::Simulation`]: crate::threadsafe::Simulation
/// [`threadsafe::Simulation::current_time()`]: crate::threadsafe::Simulation::current_time
/// [`threadsafe::Simulation::schedule()`]: crate::threadsafe::Simulation::schedule
/// [`ordered-float`]: https://docs.rs/ordered-float/4
/// [`OrderedFloat`]: https://docs.rs/ordered-float/4/ordered_float/struct.OrderedFloat.html
/// [`NotNan`]: https://docs.rs/ordered-float/4/ordered_float/struct.NotNan.html
/// The generic type used for a simulation's overall state.
///
/// This type may include to-date summary statistics, collections of simulated entities, terrain maps, historical
/// records of simulated events, or whatever else is necessary to describe the real-world process or phenomenon in a
/// program.
///
/// This trait has only one method, which provides a way for the [`serial::Simulation::run()`] and
/// [`threadsafe::Simulation::run()`] methods to ask whether they should wrap up event execution. The default
/// implementation of this method will always answer "no," and so a simulation running with the default will continue
/// until the event queue becomes empty.
///
/// Making this trait generic over the type used for clock time enables the [`is_complete()`] method to take a shared
/// reference to that type with full access to any method with a `&self` receiver.
///
/// To use your implementor with a [`threadsafe::Simulation`], it must also implement [`Sync`]. desque does not require
/// your implementor to be [`Send`], but if it is then [`threadsafe::Simulation`] will also be [`Send`].
///
/// [`serial::Simulation::run()`]: crate::serial::Simulation::run
/// [`threadsafe::Simulation`]: crate::threadsafe::Simulation
/// [`threadsafe::Simulation::run()`]: crate::threadsafe::Simulation::run
/// [`is_complete()`]: SimState::is_complete