rsynko_session/
session.rs1use crate::{Attending, AttentionAlg, ClockAlg, RunHoldAlg, RunReadAlg, UndertakingAlg, Wanted};
2use alux_ext::ext;
3use std::time::Duration;
4
5#[ext(name = SessionExt)]
7pub impl<This> This
8where
9 This: UndertakingAlg + RunReadAlg + RunHoldAlg + AttentionAlg + ClockAlg,
10{
11 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 Err(refusal) => self.ended(&id, Err(refusal)),
38 }
39 }
40 }
41
42 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 if !over {
51 match self.wanted(&attending.id) {
52 Wanted::Running => self.let_go(attending),
53 Wanted::Held => self.hold_still(attending),
54 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 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 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 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}