use std::sync::OnceLock;
use std::time::Duration;
use super::{LockGuard, LockManager};
use super::internal_memory::InternalMemoryLockManager;
pub struct MemoryLockManager;
impl MemoryLockManager {
pub fn new() -> Self {
let _ = Self::shared();
Self
}
fn shared() -> &'static InternalMemoryLockManager {
static SHARED: OnceLock<InternalMemoryLockManager> = OnceLock::new();
SHARED.get_or_init(InternalMemoryLockManager::new)
}
}
impl Default for MemoryLockManager {
fn default() -> Self { Self::new() }
}
impl std::fmt::Debug for MemoryLockManager {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MemoryLockManager").finish()
}
}
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl LockManager for MemoryLockManager {
async fn try_lock(&self, key: &str) -> Option<Box<dyn LockGuard>> {
Self::shared().try_lock(key).await
}
async fn lock(&self, key: &str, timeout: Duration) -> anyhow::Result<Box<dyn LockGuard>> {
Self::shared().lock(key, timeout).await
}
}
#[cfg(all(test, not(target_arch = "wasm32")))]
mod test {
use super::*;
#[tokio::test]
async fn two_instances_share_keys() {
let a = MemoryLockManager::new();
let b = MemoryLockManager::new();
let g = a.try_lock("bark.shared.test").await.unwrap();
let busy = b.try_lock("bark.shared.test").await;
assert!(busy.is_none(), "second instance should observe the lock");
drop(g);
let g2 = b.try_lock("bark.shared.test").await;
assert!(g2.is_some(), "second instance can acquire after release");
}
}