multishot 0.3.2

An async, lock-free, reusable channel for sending single values to asynchronous tasks.
Documentation
# multishot

An async, lock-free, reusable channel for sending single values to asynchronous
tasks.

[![Cargo](https://img.shields.io/crates/v/multishot.svg)](https://crates.io/crates/multishot)
[![Documentation](https://docs.rs/multishot/badge.svg)](https://docs.rs/multishot)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](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.