listener-holder 0.1.1

A thread-safe single-listener holder with lock-free reads for Rust
Documentation
# 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