# multishot
An async, lock-free, reusable channel for sending single values to asynchronous
tasks.
[](https://crates.io/crates/multishot)
[](https://docs.rs/multishot)
[](https://github.com/asynchronics/multishot#license)
## Overview
In a multi-shot channel, the receiver half is reusable and able to recycle the
sender half without ever re-allocating. Sending or awaiting a value and
recycling the sender are all lock-free operations, the last two being
additionally wait-free. Producing a new sender does not require additional
synchronization or spinning: it is guaranteed to succeed immediately if the
value sent by a previous sender was received.
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
multishot = "0.3.2"
```
## Example
```rust
use std::thread;
async {
let (s, mut r) = multishot::channel();
// Send a value to the channel from another thread.
thread::spawn(move || {
s.send("42");
});
// Receive the value.
let res = r.recv().await;
assert_eq!(res, Ok("42"));
// Recycle the sender. This is guaranteed to succeed if the previous
// message has been read.
let s = r.sender().unwrap();
// Drop the sender on another thread without sending a message.
thread::spawn(move || {
drop(s);
});
// Receive an error.
let res = r.recv().await;
assert_eq!(res, Err(multishot::RecvError {}));
};
```
## Safety
This is a low-level primitive and as such its implementation relies on `unsafe`.
The test suite makes extensive use of [Loom] and MIRI to assess its correctness.
As amazing as they are, however, Loom and MIRI cannot formally prove the absence
of data races so soundness issues _are_ possible.
[Loom]: https://github.com/tokio-rs/loom
## Implementation
Sending, receiving and recycling a sender are lock-free operations; the last two
are additionally wait-free.
Polling requires no read-modify-write (RMW) operation if the value is readily
available, 1 RMW if this is the first waker update and 2 RMWs otherwise. Sending
needs 1 RMW if no waker was registered, and typically 2 RMW if one was
registered. Compared to a non-reusable one-shot channel such as Tokio's, the
only extra cost is 1 RMW in case the waker was updated (which is rare in
practice). Also, the implementation of `multishot` partially offsets this extra
cost by using arithmetic atomic operations when sending rather than the
typically more expensive compare-and-swap operation.
## License
This software is licensed under the [Apache License, Version 2.0](LICENSE-APACHE) or the
[MIT license](LICENSE-MIT), at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.