Skip to main content

rsynko_session/
session.rs

1use crate::{Attending, AttentionAlg, ClockAlg, RunHoldAlg, RunReadAlg, UndertakingAlg, Wanted};
2use alux_ext::ext;
3use std::time::Duration;
4
5/// Derives one pass of attention from beginning, reading, holding, and ending runs.
6#[ext(name = SessionExt)]
7pub impl<This> This
8where
9    This: UndertakingAlg + RunReadAlg + RunHoldAlg + AttentionAlg + ClockAlg,
10{
11    /// Attends to every run once, then begins the work nobody has begun yet.
12    ///
13    /// The order is the meaning. Ending comes before beginning, so leaving never races starting;
14    /// a run is seen to be over before it is read, so everything it wrote before ending is read;
15    /// and what it said is stated before how it ended, so nothing it said is lost to its ending.
16    fn attend(&mut self, running: &mut Vec<Attending<This::Id, This::Run, This::Moment>>) {
17        let mut index = 0;
18        while index < running.len() {
19            if self.attend_one(&mut running[index]) {
20                index += 1;
21                continue;
22            }
23            let attending = running.swap_remove(index);
24            let ending = self.end_run(attending.run);
25            self.ended(&attending.id, ending);
26        }
27        let holdable = self.holding_is_possible();
28        for id in self.unattended() {
29            match self.begin(&id) {
30                Ok(run) => {
31                    self.begun(&id, holdable);
32                    let began = self.now();
33                    running.push(Attending::begun(id, run, began));
34                }
35                // A refusal to begin is how that work ended, and is stated once rather than
36                // retried: what refused it is the request, which has not changed.
37                Err(refusal) => self.ended(&id, Err(refusal)),
38            }
39        }
40    }
41
42    /// Attends to one run, and states whether it is still running afterward.
43    fn attend_one(&mut self, attending: &mut Attending<This::Id, This::Run, This::Moment>) -> bool {
44        let over = self.run_is_over(&attending.run);
45        for report in self.read_run(&mut attending.run) {
46            self.heard(&attending.id, report);
47        }
48        // A run that is over is past wanting: holding it still or telling it to stop would say
49        // something about a run that is no longer happening.
50        if !over {
51            match self.wanted(&attending.id) {
52                Wanted::Running => self.let_go(attending),
53                Wanted::Held => self.hold_still(attending),
54                // A run is another program: leaving without ending it leaves it running.
55                Wanted::Unwanted => self.abandon_run(&mut attending.run),
56            }
57        }
58        let elapsed = self.running_for(attending);
59        self.ran_for(&attending.id, elapsed);
60        !over
61    }
62
63    /// Holds one run still, and remembers when, so held time is not counted as running.
64    fn hold_still(&self, attending: &mut Attending<This::Id, This::Run, This::Moment>) {
65        if attending.held_since.is_none() {
66            self.hold_run(&mut attending.run, true);
67            attending.held_since = Some(self.now());
68        }
69    }
70
71    /// Lets one held run go, keeping the time it was held still.
72    fn let_go(&self, attending: &mut Attending<This::Id, This::Run, This::Moment>) {
73        if let Some(held_since) = attending.held_since.take() {
74            attending.held_for = attending.held_for.saturating_add(self.since(&held_since));
75            self.hold_run(&mut attending.run, false);
76        }
77    }
78
79    /// States how long one run has been running, not counting the time it was held still.
80    fn running_for(&self, attending: &Attending<This::Id, This::Run, This::Moment>) -> Duration {
81        let holding = attending.held_since.as_ref().map_or(Duration::ZERO, |at| self.since(at));
82        self.since(&attending.began).saturating_sub(attending.held_for).saturating_sub(holding)
83    }
84}