#[cfg(target_os = "macos")]
use std::sync::{Condvar, Mutex, OnceLock};
#[cfg(target_os = "macos")]
const MAX_MANAGED_WRITERS: usize = 4;
#[cfg(target_os = "macos")]
#[derive(Default)]
struct WriterState {
active: usize,
}
#[cfg(target_os = "macos")]
fn writer_gate() -> &'static (Mutex<WriterState>, Condvar) {
static GATE: OnceLock<(Mutex<WriterState>, Condvar)> = OnceLock::new();
GATE.get_or_init(|| (Mutex::new(WriterState::default()), Condvar::new()))
}
#[cfg(target_os = "macos")]
fn acquisition_gate() -> &'static Mutex<()> {
static GATE: OnceLock<Mutex<()>> = OnceLock::new();
GATE.get_or_init(|| Mutex::new(()))
}
#[doc(hidden)]
pub struct LmdbWritePermit {
#[cfg(target_os = "macos")]
held: bool,
}
#[doc(hidden)]
pub fn acquire_lmdb_write_permit() -> LmdbWritePermit {
#[cfg(target_os = "macos")]
{
let (lock, available) = writer_gate();
let mut state = lock.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
while state.active >= MAX_MANAGED_WRITERS {
state = available
.wait(state)
.unwrap_or_else(|poisoned| poisoned.into_inner());
}
state.active += 1;
LmdbWritePermit { held: true }
}
#[cfg(not(target_os = "macos"))]
{
LmdbWritePermit {}
}
}
#[doc(hidden)]
pub fn with_lmdb_lock_acquisition<T>(operation: impl FnOnce() -> T) -> T {
#[cfg(target_os = "macos")]
{
let _guard = acquisition_gate()
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
operation()
}
#[cfg(not(target_os = "macos"))]
{
operation()
}
}
impl Drop for LmdbWritePermit {
fn drop(&mut self) {
#[cfg(target_os = "macos")]
if self.held {
let (lock, available) = writer_gate();
let mut state = lock.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
state.active = state
.active
.checked_sub(1)
.expect("LMDB writer permit count underflow");
self.held = false;
available.notify_one();
}
}
}