Closed emacsist closed 3 years ago
@emacsist https://stackoverflow.com/questions/62351945/alternative-to-using-await-with-lazy-static-macro-in-rust Check if this can help you
I'm also interested in having async initialization functions. This seems pretty straight-forward to implement, at least for the unsync
version of OnceCell
. For example, the async version of get_or_try_init
looks almost exactly like the original version (with a bit more type annotations):
pub async fn get_or_try_init<I, F, E>(&self, init: I) -> Result<&T, E> where I: FnOnce() -> F, F: Future<Output=Result<T, E>> {
if let Some(val) = self.get() {
Ok(val)
} else {
let val = init().await?;
assert!(self.set(val).is_ok(), "reentrant init");
Ok(self.get().unwrap())
}
}
Do you still believe this require writing another crate for this? I could do it, but I'm afraid it would just be a copy-paste of this crate with some await
added.
I've thought about this some more, and now I think it would be a bad idea to provide async version of get_or_init. If you need asyc_get_or_init
, than there's an await inside the closure. That means that, mid-initialization, the closure would get suspended, and whatever code will be run instead. This code may try to init the same cell and block (that is, get
needs to be async as well). This I think would be surprising, and a manual call to get
/ set
would probably be less confusing about runtime semantics.
With that in mind, the decision is that async is explicitly out of scope for once_cell. I might be wrong, of course, the good way to prove that is to publish an async_once_cell
to crates.io and to show that in practice the problems are not as big as I fear. I'll gladly link the crate from readme.
I found out I could use block_on
to skirt this issue,
Tokio also provides asyncified OnceCell: https://docs.rs/tokio/1.5.0/tokio/sync/struct.OnceCell.html.
Good question! At the moment, OnceCell provides only blocking API. async API seems plausible, but I don’t immediately know what it should look like exactly, as I am not async expert. I think it makes sense to implement this as a new crate, asyn_once_cell, at least initially.