# listener-holder
A **thread-safe**, **lock-free read** single-listener holder for Rust.
Use it when you have one optional callback/listener that may be set or cleared at runtime, and you want to notify it from any thread without repeating `RwLock<Option<...>>` boilerplate.
## Requirements
- The listener type `L` must implement `Send + Sync`. The holder is then safe to share across threads (e.g. via `Arc<ListenerHolder<L>>`).
## Features
- **Thread-safe**: `ListenerHolder<L>` is `Send + Sync` when `L: Send + Sync`. Safe to share via `Arc` across threads.
- **Lock-free reads**: Uses [arc-swap](https://docs.rs/arc-swap) internally; getting and notifying the listener do not take a lock. See [docs/CONCURRENCY.md](docs/CONCURRENCY.md) for comparison with `RwLock<Option<Arc<L>>>`.
- **Single listener**: Holds at most one listener; setting a new one replaces the previous.
- **Simple API**: `set` (pass `None` to clear), `with_listener`, `get`.
## Usage
```toml
[dependencies]
listener-holder = "0.1.1"
```
```rust
use listener_holder::ListenerHolder;
use std::sync::Arc;
// Your listener type must be Send + Sync
struct MyListener;
impl MyListener {
fn on_event(&self, msg: &str) {
println!("event: {}", msg);
}
}
let holder = ListenerHolder::new();
// Set listener
holder.set(Some(Arc::new(MyListener)));
// Notify (only if listener is set)
holder.with_listener(|l| l.on_event("hello"));
// Clear (pass None)
holder.set(None);
holder.with_listener(|l| l.on_event("ignored")); // no-op
// Get a clone of the current listener (e.g. to call from async code outside the lock)
if let Some(listener) = holder.get() {
listener.on_event("from get()");
}
```
## When to use
- SDK or engine that exposes a single optional listener (e.g. connection listener, migration progress listener).
- You were about to write `RwLock<Option<Arc<dyn Listener>>>` and want a ready-made type instead.
## Panics
- [`with_listener`] does not panic by itself. If the closure you pass panics, the holder is left unchanged and other threads can continue to use it.
- No other method panics under normal use.
[`with_listener`]: https://docs.rs/listener-holder/latest/listener_holder/struct.ListenerHolder.html#method.with_listener
## License
MIT OR Apache-2.0