sim_lib_control/
policy.rs1use std::{
2 collections::BTreeSet,
3 sync::{Arc, Mutex},
4};
5
6use sim_kernel::{
7 Cx, Error, Ref, Result,
8 control::{
9 ControlAbort, ControlCapture, ControlPolicy, ControlPolicyRef, ControlPrompt,
10 ControlResume, aborted_control_result, captured_control_result, resumed_control_result,
11 },
12};
13
14pub struct OneShotControlPolicy {
20 resumed: Mutex<BTreeSet<Ref>>,
21}
22
23impl OneShotControlPolicy {
24 pub fn new() -> Self {
26 Self {
27 resumed: Mutex::new(BTreeSet::new()),
28 }
29 }
30}
31
32impl Default for OneShotControlPolicy {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl ControlPolicy for OneShotControlPolicy {
39 fn name(&self) -> &'static str {
40 "one-shot-control"
41 }
42
43 fn enter_prompt(&self, _cx: &mut Cx, _prompt: &ControlPrompt) -> Result<()> {
44 Ok(())
45 }
46
47 fn capture(&self, cx: &mut Cx, capture: &ControlCapture) -> Result<Ref> {
48 captured_control_result(cx, capture.continuation.clone(), capture.value.clone())
49 }
50
51 fn abort(&self, cx: &mut Cx, abort: &ControlAbort) -> Result<Ref> {
52 aborted_control_result(cx, abort.prompt.clone(), abort.value.clone())
53 }
54
55 fn resume(&self, cx: &mut Cx, resume: &ControlResume) -> Result<Ref> {
56 let mut resumed = self
57 .resumed
58 .lock()
59 .map_err(|_| Error::PoisonedLock("one-shot control policy"))?;
60 if !resumed.insert(resume.continuation.clone()) {
61 return Err(Error::Eval(
62 "one-shot control continuation already resumed".to_owned(),
63 ));
64 }
65 resumed_control_result(cx, resume.continuation.clone(), resume.value.clone())
66 }
67}
68
69pub struct SegmentedControlPolicy {
74 segment: Ref,
75 one_shot: OneShotControlPolicy,
76}
77
78impl SegmentedControlPolicy {
79 pub fn new(segment: Ref) -> Self {
81 Self {
82 segment,
83 one_shot: OneShotControlPolicy::new(),
84 }
85 }
86
87 pub fn segment(&self) -> &Ref {
89 &self.segment
90 }
91}
92
93impl ControlPolicy for SegmentedControlPolicy {
94 fn name(&self) -> &'static str {
95 "segmented-control"
96 }
97
98 fn enter_prompt(&self, cx: &mut Cx, prompt: &ControlPrompt) -> Result<()> {
99 self.one_shot.enter_prompt(cx, prompt)
100 }
101
102 fn capture(&self, cx: &mut Cx, capture: &ControlCapture) -> Result<Ref> {
103 self.one_shot.capture(cx, capture)
104 }
105
106 fn abort(&self, cx: &mut Cx, abort: &ControlAbort) -> Result<Ref> {
107 self.one_shot.abort(cx, abort)
108 }
109
110 fn resume(&self, cx: &mut Cx, resume: &ControlResume) -> Result<Ref> {
111 self.one_shot.resume(cx, resume)
112 }
113}
114
115pub fn one_shot_control_policy() -> ControlPolicyRef {
118 Arc::new(OneShotControlPolicy::new())
119}
120
121pub fn segmented_control_policy(segment: Ref) -> ControlPolicyRef {
124 Arc::new(SegmentedControlPolicy::new(segment))
125}
126
127pub fn install_control_policy(cx: &mut Cx) {
130 cx.set_control_policy(one_shot_control_policy());
131}