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
use std::{cell::RefCell, rc::Rc};

use super::{Duration, Instant, Reaction, Sched};

/// Enumeration of different policies for handling events that succeed one another more rapidly than
/// is allowed by a physical action's min. inter-arrival time.
#[derive(Eq, PartialEq, Debug)]
pub enum QueuingPolicy {
    /// For logical actions, the policy should always be `NONE`.
    NONE,
    /// For physical actions, the default policy is `DEFER`, which is to increase the offsets of
    /// newly-scheduled events so that the min. inter-arrival time is satisfied. This means that no
    /// events will be ignored, but they will occur later. This policy has the drawback that it may
    /// cause the event queue to grow indefinitely.
    DEFER,
    /// The `DROP` policy ignores events that are scheduled too close to one another.
    DROP,
    /// The `UPDATE` policy does the following. If the time that a newly-scheduled event is in too
    /// close proximity or is still on the event queue, the value carried by that event will be
    /// updated with the value of the newly-scheduled event. If this is not possible because the
    /// original event has already been popped off the queue, the `DEFER` policy applies.
    UPDATE,
}

/// Reaction activation record to push onto the reaction queue.
#[derive(Eq, PartialEq, Debug)]
pub struct Trigger<S>
where
    S: Sched,
{
    /// Reactions sensitive to this trigger.
    pub reactions: Vec<Rc<Reaction<S>>>,
    /// For a logical action, this will be a minimum delay. For physical, it is the minimum
    /// interarrival time.
    pub offset: Option<Duration>,
    /// For an action, this is not used.
    pub period: Option<Duration>,
    /// Pointer to malloc'd value (or None)
    pub value: Rc<RefCell<Option<S::Value>>>,
    /// Indicator that this denotes a physical action (i.e., to be scheduled relative to physical
    /// time).
    pub is_physical: bool,
    /// Tag of the last event that was scheduled for this action.
    pub scheduled: RefCell<Option<Instant>>,
    /// Indicates the policy for handling events that succeed one another more rapidly than
    /// allowable by the specified min. interarrival time. Only applies to physical actions.
    pub policy: QueuingPolicy,
}

impl<S> Trigger<S>
where
    S: Sched,
{
    pub fn new(
        reactions: Vec<Rc<Reaction<S>>>,
        offset: Option<Duration>,
        period: Option<Duration>,
        is_physical: bool,
        policy: QueuingPolicy,
    ) -> Self {
        Self {
            reactions,
            offset,
            period,
            value: Rc::new(RefCell::new(None)),
            is_physical,
            scheduled: RefCell::new(None),
            policy,
        }
    }
}