Git Product home page Git Product logo

whisk's Introduction

Whisk

tests GitHub commit activity GitHub contributors
Crates.io Crates.io Crates.io (recent)
Crates.io Docs.rs

Simple and fast lockless async channels

Simple and fast async channels that can be used to implement futures, streams, notifiers, and actors. Whisk is purposely kept small, implemented in under 1000 lines of Rust code, with zero dependencies (not including feature flags to enable implementation of traits from other crates) - and also works on no_std!

MSRV

Whisk targets Rust 1.65 and later.

Benchmarks

Naïve benchmarks for v0.10.0 actor on pasts runtime (compared with dynamic library):

Dynamic library: 6ns
Whisk (2-thread): 4.396µs
Flume (2-thread): 4.594µs
Whisk (1-thread): 277ns
Flume (1-thread): 325ns

whisk's People

Contributors

aldaronlau avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

notapenguin0

whisk's Issues

Avoid implementing `Future` directly on `Commander` and `Messenger`

Future types are not really meant to be .awaited more than once. Rust does technically allow it, but it makes for a counterintuitive and abnormal API. Additionally, (&mut commander).await looks worse IMO than something like commander.next().await or commander.recv().await.

I suggest to either implement Stream which has the exact semantics that you want from the current Future implementation, or to provide an async fn recv(&mut self) instead.

unable to use poll_next() from Channel's Stream impl (with futures_core enabled, possibly two runtimes conflict?)

Describe the bug
Unable to use .poll_next() on a Channel<Option>.

To Reproduce
Steps to reproduce the behavior:

  1. Add crate whisk, version 0.11.0, with features futures_core
  2. Add crate tokio, version 1.28.2, features: rt-multi-thread, macros
  3. Create channel with Channel::new()
  4. clone channel and give clone to tokio async task (two runtimes?, am not using async::main)
  5. no method 'poll_next' found for struct 'Channel<Option>' (the original channel pointer)

Expected behavior
the method 'poll_next' returns an option within a for loop:
Some(VideoUpdate)
or None for channel has been cleared

Screenshots
If applicable, add screenshots to help explain your problem.
Screenshot from 2023-05-31 12-45-06

Desktop (please complete the following information):

  • OS: [e.g. iOS]
    Linux 5.15.0-71-generic #78~20.04.1-Ubuntu SMP Wed Apr 19 11:26:48 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Additional context
I am pretty new to programming but I imagine there could be some conflicts between two async runtimes pasts and tokio,
I aim for my crate to be easily made nostd, but also trying to balance that with readability to a client who does not understand
the details, so using tokio's task and writing it like a thread spawn with task::spawn is very nice, and I would love to be able to
understand more about how I would create a similar interface using only pasts as nostd is the end goal.

New `Waker`s are incorrectly ignored

The future contract is such that:

  • When poll is called multiple times, the wakers are not guaranteed to be the same.
  • Waking a waker from an old call to poll may not have any effect.
  • If you return Poll::Ready from poll, the waker you have is basically completely worthless.
  • If you return Poll::Pending from poll, but have not woken or cloned the waker given to you in that poll call's cx.waker(), you may wait forever.

This crate makes many assumptions about how the caller gives its futures wakers that do not hold under Future's contract. This means that it's possible that perfectly valid executor implementations would leave this crate's futures hanging forever. What you need to do is update the stored waker each time poll is called. Be careful about data races though, storing a new waker is not atomic so you'll have to use additional atomics to synchronize it.

Route To 1.0.0

  • Remove Weak::try_recv() #23
  • Wait for pasts 1.0.0, or find a way to make backwards compatible (old pasts versions depending on new - but not exactly?)
  • Make some functions const? Like Channel::new() and Weak::new() 1 (could be put off)
  • Do better benchmarks #21 (could be post 1.0.0)
  • Attempt lockless waker #18 (could be post 1.0.0)
  • #27 (could be post 1.0.0)
  • #31

Footnotes

  1. Edit: Would depend on https://github.com/rust-lang/rust/pull/95965 & https://github.com/rust-lang/rust/issues/79597

API improvement

commander.start().await;
for message in &mut commander {
}

Might be able to become:

for message in commander.start().await {
}

Change size of queue with const generics

Currently whisk is limited to a single element in the mpmc queue. This queue is implemented as a simple Option, but could use an implementation of a pre-allocated list with a maximum capacity set via a const generic.

Should Probably Deprecate/Remove `Weak::try_recv()`

Reason:

It's virtually impossible to guarantee that it won't wait indefinitely.

  • Weak is upgraded internally for duration of receive
  • Channel (original) is dropped
  • Waiting on channel with no senders

Weak senders on the other hand:

  • Weak is upgraded internally for duration of send
  • Channel (original) is dropped
  • Send to channel with no receiver(s)
  • Send complete

`Message` Is Mostly? Useless

The public api Message type doesn't do much and could be replaced with impl Future<Output = ()> + Send + Sync + Unpin

API: Type mapping

Allocation Reduction

Should be able to create a custom struct that contains a whisk::Channel and constructs as Arc<Self> containing the channel (but not within another Arc).

#[derive(Clone)]
struct MyChannelWrapper<T, U> {
   data: T,
   channel: whisk::Channel<U>,
}

impl<T, U> MyChannelWrapper<T, U> {
    fn new() -> Arc<Self> { ... }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.