singleton_registry/lib.rs
1//! # Singleton Registry
2//!
3//! A thread-safe singleton registry for Rust.
4//! Store and retrieve **any type** with isolated registries.
5//! Each type can have only **one instance** per registry.
6//!
7//! ## Features
8//!
9//! - **Thread-safe**: All operations safe across multiple threads
10//! - **Isolated registries**: Create multiple independent registries with `define_registry!`
11//! - **True singleton**: Only one instance per type per registry
12//! - **Override-friendly**: Later registrations replace previous ones
13//! - **Write-once, read-many**: Optimized for configuration and shared resources
14//! - **Tracing support**: Optional callback system for monitoring
15//!
16//! ## Usage
17//!
18//! ```rust
19//! use singleton_registry::define_registry;
20//! use std::sync::Arc;
21//!
22//! define_registry!(app);
23//!
24//! app::set_trace_callback(|event| {
25//! println!("Registry event: {}", event);
26//! });
27//!
28//! app::register(12i32);
29//! app::register("config".to_string());
30//!
31//! let multiply_by_two: fn(i32) -> i32 = |x| x * 2;
32//! app::register(multiply_by_two);
33//!
34//! assert!(app::contains::<i32>().unwrap());
35//!
36//! let number: Arc<i32> = app::get().unwrap();
37//! let config: Arc<String> = app::get().unwrap();
38//! let doubler: Arc<fn(i32) -> i32> = app::get().unwrap();
39//!
40//! let result = doubler(21);
41//!
42//! assert_eq!(result, 42);
43//! assert_eq!(*number, 12);
44//! assert_eq!(&*config, "config");
45//! ```
46//!
47//! ## Core API
48//!
49//! - [`define_registry!`] - Macro to create a registry module with free functions
50//! - [`RegistryApi`] - Trait defining registry operations (for advanced usage)
51//! - [`RegistryEvent`] - Events emitted during operations (for tracing)
52//! - [`RegistryError`] - Error type for registry operations
53//!
54//! ## Tracing
55//!
56//! The tracing callback system allows you to monitor registry operations:
57//!
58//! - Callbacks are invoked for `register`, `get`, and `contains` operations
59//! - Callbacks survive registry `clear()` operations (test-only method)
60//! - Use `clear_trace_callback()` to remove the callback
61//! - If a callback panics, the panic propagates (registry lock is not held)
62//!
63//! ## Error Handling
64//!
65//! All fallible operations return `Result<T, RegistryError>`:
66//!
67//! - `TypeNotFound` - The requested type is not registered
68//! - `TypeMismatch` - Internal type mismatch (should never happen)
69//! - `RegistryLock` - Lock poisoning (automatically recovered)
70//!
71//! Lock poisoning is automatically recovered by extracting the inner value.
72//! This is safe because registry operations are idempotent.
73
74mod macros;
75mod registry_error;
76mod registry_event;
77mod registry_trait;
78
79// Re-export the public API
80pub use registry_error::RegistryError;
81pub use registry_event::RegistryEvent;
82pub use registry_trait::RegistryApi;
83
84// Macros are exported via #[macro_export] in macros.rs
85// They are automatically available at crate root