/*! * Provider Lock (skeleton) * * Phase 15.5 受け口: 型→Provider のロック状態を保持するための最小スケルトン。 * 既定では挙動を変えず、環境変数により警告/エラー化のみ可能にする。 */ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, OnceLock}; use crate::boxes::file::provider::{FileCaps, FileIo}; static LOCKED: AtomicBool = AtomicBool::new(false); static WARN_ONCE: OnceLock<()> = OnceLock::new(); static FILEBOX_PROVIDER: OnceLock> = OnceLock::new(); /// Return true when providers are locked pub fn is_locked() -> bool { LOCKED.load(Ordering::Relaxed) } /// Lock providers (idempotent) pub fn lock_providers() { LOCKED.store(true, Ordering::Relaxed); } /// Guard called before creating a new box instance. /// Default: no-op. When NYASH_PROVIDER_LOCK_STRICT=1, returns Err if not locked. /// When NYASH_PROVIDER_LOCK_WARN=1, prints a warning once. pub fn guard_before_new_box(box_type: &str) -> Result<(), String> { if is_locked() { return Ok(()); } let strict = std::env::var("NYASH_PROVIDER_LOCK_STRICT").ok().as_deref() == Some("1"); let warn = std::env::var("NYASH_PROVIDER_LOCK_WARN").ok().as_deref() == Some("1"); if strict { return Err(format!("E_PROVIDER_NOT_LOCKED: attempted to create '{}' before Provider Lock", box_type)); } if warn { // Print once per process let _ = WARN_ONCE.get_or_init(|| { eprintln!("[provider-lock][warn] NewBox emitted before Provider Lock. Set NYASH_PROVIDER_LOCK_STRICT=1 to error."); }); } Ok(()) } /// Set the global FileBox provider (can only be called once) pub fn set_filebox_provider(provider: Arc) -> Result<(), String> { FILEBOX_PROVIDER.set(provider) .map_err(|_| "FileBox provider already set".to_string()) } /// Get the global FileBox provider pub fn get_filebox_provider() -> Option<&'static Arc> { FILEBOX_PROVIDER.get() } /// Convenience: fetch current FileBox provider capabilities (if initialized). /// Returns None when no provider is registered yet. pub fn get_filebox_caps() -> Option { get_filebox_provider().map(|p| p.caps()) }