pub struct IdleAction { /* private fields */ }
Expand description
A state machine that performs an action during idle periods.
This could be used to invoke std::thread::sleep
during idle periods to save CPU time.
Implementations§
Source§impl IdleAction
impl IdleAction
Sourcepub fn new(thresh: usize, action: Box<dyn FnMut()>) -> Self
pub fn new(thresh: usize, action: Box<dyn FnMut()>) -> Self
Creates a new IdleAction
that triggers automatically after max_yields
idle steps.
Examples found in repository?
examples/basic.rs (line 136)
99fn main() {
100 // read in an xml file whose path is given as a command line argument
101 let args = std::env::args().collect::<Vec<_>>();
102 if args.len() != 2 {
103 panic!("usage: {} [xml file]", &args[0]);
104 }
105 let mut xml = String::new();
106 std::fs::File::open(&args[1]).expect("failed to open file").read_to_string(&mut xml).expect("failed to read file");
107
108 // create a new shared clock and start a thread that updates it at our desired interval
109 let clock = Arc::new(Clock::new(UtcOffset::UTC, Some(Precision::Medium)));
110 let clock_clone = clock.clone();
111 std::thread::spawn(move || loop {
112 std::thread::sleep(CLOCK_INTERVAL);
113 clock_clone.update();
114 });
115
116 // create a custom config for the system - in this simple example we just implement the say/think blocks to print to stdout
117 let config = Config::<C, StdSystem<C>> {
118 request: None,
119 command: Some(Rc::new(|_mc, key, command, _proc| match command {
120 Command::Print { style: _, value } => {
121 if let Some(value) = value {
122 println!("{value:?}");
123 }
124 key.complete(Ok(())); // any request that you handle must be completed - otherwise the calling process will hang forever
125 CommandStatus::Handled
126 }
127 _ => CommandStatus::UseDefault { key, command }, // anything you don't handle should return the key and command to invoke the default behavior instead
128 })),
129 };
130
131 // initialize our system with all the info we've put together
132 let system = Rc::new(StdSystem::new_sync(CompactString::new(BASE_URL), None, config, clock.clone()));
133 let mut env = get_running_project(&xml, system);
134
135 // begin running the code - these are some helpers to make things more efficient in terms of memory and cpu resources
136 let mut idle_sleeper = IdleAction::new(YIELDS_BEFORE_SLEEP, Box::new(|| std::thread::sleep(IDLE_SLEEP_TIME)));
137 let mut next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
138 loop {
139 env.mutate(|mc, env| {
140 let mut proj = env.proj.borrow_mut(mc);
141 for _ in 0..1024 {
142 // step the virtual machine forward by one bytecode instruction
143 let res = proj.step(mc);
144 if let ProjectStep::Error { error, proc } = &res {
145 // if we get an error, we can generate an error summary including a stack trace - here we just print out the result
146 let trace = ErrorSummary::extract(error, proc, &env.locs);
147 println!("error: {error:?}\ntrace: {trace:?}");
148 }
149 // this takes care of performing thread sleep if we get a bunch of no-ops from proj.step back to back
150 idle_sleeper.consume(&res);
151 }
152 });
153 // if it's time for us to do garbage collection, do it and reset the next collection time
154 if clock.read(Precision::Low) >= next_collect {
155 env.collect_all();
156 next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
157 }
158 }
159}
Sourcepub fn consume<C: CustomTypes<S>, S: System<C>>(
&mut self,
res: &ProjectStep<'_, C, S>,
)
pub fn consume<C: CustomTypes<S>, S: System<C>>( &mut self, res: &ProjectStep<'_, C, S>, )
Consumes a step result and advances the state machine. If the step resulting in an idle action, this may trigger the idle action to fire and reset the state machine.
Examples found in repository?
examples/basic.rs (line 150)
99fn main() {
100 // read in an xml file whose path is given as a command line argument
101 let args = std::env::args().collect::<Vec<_>>();
102 if args.len() != 2 {
103 panic!("usage: {} [xml file]", &args[0]);
104 }
105 let mut xml = String::new();
106 std::fs::File::open(&args[1]).expect("failed to open file").read_to_string(&mut xml).expect("failed to read file");
107
108 // create a new shared clock and start a thread that updates it at our desired interval
109 let clock = Arc::new(Clock::new(UtcOffset::UTC, Some(Precision::Medium)));
110 let clock_clone = clock.clone();
111 std::thread::spawn(move || loop {
112 std::thread::sleep(CLOCK_INTERVAL);
113 clock_clone.update();
114 });
115
116 // create a custom config for the system - in this simple example we just implement the say/think blocks to print to stdout
117 let config = Config::<C, StdSystem<C>> {
118 request: None,
119 command: Some(Rc::new(|_mc, key, command, _proc| match command {
120 Command::Print { style: _, value } => {
121 if let Some(value) = value {
122 println!("{value:?}");
123 }
124 key.complete(Ok(())); // any request that you handle must be completed - otherwise the calling process will hang forever
125 CommandStatus::Handled
126 }
127 _ => CommandStatus::UseDefault { key, command }, // anything you don't handle should return the key and command to invoke the default behavior instead
128 })),
129 };
130
131 // initialize our system with all the info we've put together
132 let system = Rc::new(StdSystem::new_sync(CompactString::new(BASE_URL), None, config, clock.clone()));
133 let mut env = get_running_project(&xml, system);
134
135 // begin running the code - these are some helpers to make things more efficient in terms of memory and cpu resources
136 let mut idle_sleeper = IdleAction::new(YIELDS_BEFORE_SLEEP, Box::new(|| std::thread::sleep(IDLE_SLEEP_TIME)));
137 let mut next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
138 loop {
139 env.mutate(|mc, env| {
140 let mut proj = env.proj.borrow_mut(mc);
141 for _ in 0..1024 {
142 // step the virtual machine forward by one bytecode instruction
143 let res = proj.step(mc);
144 if let ProjectStep::Error { error, proc } = &res {
145 // if we get an error, we can generate an error summary including a stack trace - here we just print out the result
146 let trace = ErrorSummary::extract(error, proc, &env.locs);
147 println!("error: {error:?}\ntrace: {trace:?}");
148 }
149 // this takes care of performing thread sleep if we get a bunch of no-ops from proj.step back to back
150 idle_sleeper.consume(&res);
151 }
152 });
153 // if it's time for us to do garbage collection, do it and reset the next collection time
154 if clock.read(Precision::Low) >= next_collect {
155 env.collect_all();
156 next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
157 }
158 }
159}
Auto Trait Implementations§
impl Freeze for IdleAction
impl !RefUnwindSafe for IdleAction
impl !Send for IdleAction
impl !Sync for IdleAction
impl Unpin for IdleAction
impl !UnwindSafe for IdleAction
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more