use crate::timer::internal::tokio_runtime_liveness::TokioRuntimeLiveness;
use std::{
collections::HashMap,
sync::{
Arc,
LazyLock,
Mutex,
Weak,
},
};
use tokio::runtime::{
Handle,
Id,
};
static REGISTRY: LazyLock<TokioRuntimeLivenessRegistry> =
LazyLock::new(TokioRuntimeLivenessRegistry::default);
#[derive(Debug, Default)]
pub(crate) struct TokioRuntimeLivenessRegistry {
entries: Mutex<HashMap<Id, Weak<TokioRuntimeLiveness>>>,
}
impl TokioRuntimeLivenessRegistry {
#[must_use]
pub(crate) fn current() -> Arc<TokioRuntimeLiveness> {
REGISTRY.get_or_create(Handle::current().id())
}
fn get_or_create(&self, runtime_id: Id) -> Arc<TokioRuntimeLiveness> {
let (liveness, release_notification) = {
let mut entries = self.entries.lock().expect(
"Tokio runtime-liveness registry lock should not be poisoned",
);
entries.retain(|_, liveness| liveness.strong_count() != 0);
if let Some(liveness) =
entries.get(&runtime_id).and_then(Weak::upgrade)
&& !liveness.is_shutdown()
{
return liveness;
}
let (liveness, release_notification) = TokioRuntimeLiveness::new();
let liveness = Arc::new(liveness);
entries.insert(runtime_id, Arc::downgrade(&liveness));
(liveness, release_notification)
};
liveness.start(release_notification);
liveness
}
}