#[cfg(not(target_arch = "wasm32"))]
use std::time::SystemTime;
#[must_use]
#[cfg(target_arch = "wasm32")]
pub(crate) fn local_instruction_counter() -> u64 {
ic_platform::ic0::performance_counter(1)
}
#[must_use]
#[cfg(all(not(test), not(target_arch = "wasm32")))]
pub(crate) const fn local_instruction_counter() -> u64 {
0
}
#[cfg(all(test, not(target_arch = "wasm32")))]
thread_local! {
static TEST_INSTRUCTIONS: std::cell::Cell<u64> = const { std::cell::Cell::new(0) };
}
#[cfg(all(test, not(target_arch = "wasm32")))]
pub(crate) fn local_instruction_counter() -> u64 {
TEST_INSTRUCTIONS.with(std::cell::Cell::get)
}
#[cfg(all(test, not(target_arch = "wasm32")))]
pub(crate) fn with_instruction_counter_for_tests<R>(
initial: u64,
run: impl FnOnce(&std::cell::Cell<u64>) -> R,
) -> R {
struct RestoreCounter<'a>(&'a std::cell::Cell<u64>, u64);
impl Drop for RestoreCounter<'_> {
fn drop(&mut self) {
self.0.set(self.1);
}
}
TEST_INSTRUCTIONS.with(|counter| {
let _restore = RestoreCounter(counter, counter.replace(initial));
run(counter)
})
}
#[must_use]
#[cfg_attr(
not(target_arch = "wasm32"),
expect(
clippy::cast_possible_truncation,
reason = "millisecond epoch values fit into u64 for IcyDB timestamps"
)
)]
pub(crate) fn now_millis() -> u64 {
#[cfg(target_arch = "wasm32")]
{
ic_platform::ic0::time() / 1_000_000
}
#[cfg(not(target_arch = "wasm32"))]
{
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(duration) => duration.as_millis() as u64,
Err(_) => 0,
}
}
}