Struct Clock

Source
pub struct Clock { /* private fields */ }
Expand description

A clock with optional coarse granularity.

Implementations§

Source§

impl Clock

Source

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}
Source

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}
Source

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,