pub struct Clock { /* private fields */ }
Expand description
A clock with optional coarse granularity.
Implementations§
Source§impl Clock
impl Clock
Sourcepub fn new(utc_offset: UtcOffset, cache_precision: Option<Precision>) -> Self
pub fn new(utc_offset: UtcOffset, cache_precision: Option<Precision>) -> Self
Creates a new Clock
with the specified UtcOffset
and (optional) cache Precision
(see Clock::read
).
Examples found in repository?
examples/basic.rs (line 109)
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 read(&self, precision: Precision) -> OffsetDateTime
pub fn read(&self, precision: Precision) -> OffsetDateTime
Reads the current time with the specified level of precision.
If caching was enabled by Clock::new
, requests at or below the cache precision level will use the cached timestamp.
In any other case, the real current time is fetched by Clock::update
and the result is stored in the cache if caching is enabled.
Examples found in repository?
examples/basic.rs (line 137)
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 update(&self) -> OffsetDateTime
pub fn update(&self) -> OffsetDateTime
Reads the real world time and stores the result in the cache if caching was enabled by Clock::new
.
Examples found in repository?
examples/basic.rs (line 113)
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 Clock
impl RefUnwindSafe for Clock
impl Send for Clock
impl Sync for Clock
impl Unpin for Clock
impl UnwindSafe for Clock
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