Reputation: 2968
In Rust, I am trying to find a way to safely set a global Instant
. Instant
is perhaps a unique form of a singleton because it has no way to initialize itself through constant function calls. Attempting to initialize a static Instant
via Instant::now()
results in the following error:
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> src/main.rs:45:24
|
45 | static EPOCH:Instant = Instant::now();
|
^^^^^^^^^^^^^^
Therefore I am looking for an ideally safe way to do the above. For context, I already have a way to do this using unsafe
rust:
use std::time::{Instant};
use std::mem::{self, MaybeUninit};
static mut MONOTONIC_EPOCH:MaybeUninit<Instant> = MaybeUninit::<Instant>::uninit();
fn set_epoch() {
unsafe {
MONOTONIC_EPOCH.as_mut_ptr().write(Instant::now());
}
}
In my use case, I need global monotonic point in time that can be used to track the time since some point in the program execution. Thus, the global Instant
does not need to be mutable after it's first set. It can be assumed that this initialization would be guaranteed in the use case to occur with only one thread active.
Note: I do need a way to control when the initialization of the Instant
occurs.
Upvotes: 4
Views: 1158
Reputation: 42718
You can use once_cell::Lazy
any of sync
or unsync
versions depending your needs:
use std::time::{Instant};
use once_cell::sync::Lazy;
static EPOCH: Lazy<Instant> = Lazy::new(Instant::now);
If you want to handle when and where initialization is done use OnceCell
instead:
use std::time::{Instant};
use once_cell::sync::OnceCell;
static EPOCH: OnceCell<Instant> = OnceCell::new();
fn main() {
let instant = EPOCH.get_or_init(Instant::now);
println!("{:?}", *instant);
}
Upvotes: 2