Giter VIP home page Giter VIP logo

pasts's Introduction

Pasts

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

Minimal and simpler alternative to the futures crate.

The pasts asynchronous runtime is designed for creating user-space software and embedded software using an asynchronous event loop. It aims to abstract away all of the pain points of using asynchronous Rust. Pasts is purposely kept small with the entire source directory under 500 lines of Rust code.

Check out the documentation for examples.

Goals

  • No unsafe (safe and sound)
  • No required std (executor requires two allocations at startup, if needed can use a bump allocator with small capacity)
  • No macros (fast compile times)
  • No dependencies1 (bloat-free)
  • No cost (true zero-cost abstractions)
  • No pain (API super easy to learn & use)
  • No platform-specific API differences (code works everywhere).

Supported Platforms

Pasts targets all platforms that can run Rust. The executor works on at least the following platforms (may work on others):

  • All platforms that support threading (includes all tier 1 and some tier 2, 3)
  • Web Assembly In Browser (Tier 2)
  • No standard devices (Tiers 2 and 3)

License

Copyright © 2019-2023 The Pasts Contributors.

Licensed under any of

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 licensed as described above, without any additional terms or conditions.

Help

If you want help using or contributing to this library, feel free to send me an email at [email protected].

Related Projects

Since pasts is not an all-in-one async runtime solution, here's a list of crates that are designed to work well with pasts:

  • Async Main - Proc macro crate to remove boilerplate for the main function
  • Whisk - No-std compatible MPMC (multi-producer/multiple-consumer) asynchronous channel
  • Smelling Salts - Library for asynchronous device waking using OS APIs
  • Lookit - Library for asynchronously connecting to devices using OS APIs

Footnotes

  1. Some features require a platform integration dependency, for instance:

pasts's People

Contributors

aldaronlau avatar darksonn avatar dependabot-preview[bot] avatar dependabot[bot] avatar piragi avatar taylorjeandev avatar

Stargazers

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

Watchers

 avatar  avatar  avatar

pasts's Issues

Use Safe Pin Projection

Once there's an API in std for doing pin projection, the API could possibly be reworked so that Task and Local are Notifiers instead of Futures.

Support Executor Injection

Currently pasts always uses the same method to sleep while a future is being executed (thread parking), while calls to functions like epoll() must happen on a separate thread (as it is in smelling_salts). This could all run on the same thread if all futures on the executor were dependent on smelling_salts, but it would need to also be able to work as it does now.

Rename `Task` Type Alias

The name is somewhat misleading, since it may not truly be a "task".

Rename:

  • Local to LocalBoxNotifier
  • Task to BoxNotifier

API Improvements

  • Issues arise when trying to use Task with an internal future type and trying to get it's type (briefly started looking at updating stick crate).

  • Also, look at moving the borrow of state, or re-introducing the removed closure in on().

  • Maybe implement temporary polyfill for AsyncIterator. Explore the possibility of having types that implement that trait get provided an into_iter() method that returns an iterator of futures (to reduce API duplication).

  • Should also add an example depending on whisk, for further API testing before working on wavy crate update.

select/join allows for moving pinned futures

Sorry to be the bearer of bad news. Pinning is a tricky subject and can be quite subtle.

Describe the bug

The current implementation of select allows for moving a future which is assumed to be pinned. Among other potential issues, this enables reading freed memory in safe code.

To Reproduce

The following should showcase the issue:

Edit: More compact example, and a bit more comments.

use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::mem;
use futures::future;

use pasts::prelude::*;

async fn doit(leak: u128) {
    if leak == 42 {
        // Take a reference to leak which is a local variable to this function. And have it live across an await.
        let leak = &leak;
        println!("{} {:?}", leak, leak as *const _);

        let mut pending = true;

        // future that only returns pending the first time it's polled.
        future::poll_fn(move |_| if mem::take(&mut pending) {
            Poll::Pending
        } else {
            Poll::Ready(())
        }).await;

        println!("{} {:?}", leak, leak as *const _);
    } else {
        // do nothing to drive the select
    }
}

#[tokio::main]
async fn main() {
    let mut v = [doit(42), doit(0)];
    println!("old location of future: {:?}", v.as_ptr());

    v.select().await;

    // move the future.
    let a = std::mem::replace(&mut v[0], doit(0));
    println!("new location of future: {:?}", &a as *const _);
    a.await;
}

Running it in debug mode for me gives:

old location of future: 0x7ffe11d595b0
42 0x7ffe11d595c0
new location of future: 0x7ffe11d59618
2595995492391351414651693012353024 0x7ffe11d595c0

In effect: The second read of the reference to &foo uses an outdated memory location, since the future has been moved the second time it was polled.

Expected behavior

The select implementation should require the futures to be Unpin, or maintain Pin invariants in some other way to prevent this from compiling.

Improve Documentation

docs.rs documenation should be improved, so users of the crate are less reliant on looking at the examples directory

Optimize `Loop`

Loop could use different wakers for each task, and avoid polling every task on each wake, only polling the task that is awoken.

DynFuture is unsound

Describe the bug

https://github.com/AldaronLau/pasts/blob/675bd309d609111fac52889602e31c9609e7f2ea/src/dyn_future.rs#L21-L22

This is Pin<&mut Type> to Pin<Field> projection and is unsound if dyn Future is not Unpin (you can move dyn Future after DynFuture dropped).

repro: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b2564e36d16d7b2a8f14f763a9477a85

The correct projection is Pin<&mut Type> to Pin<&mut Field>. In DynFuture, it is Pin<&mut DynFuture<'_, T>> to Pin<&mut &mut dyn Future>, and it needs to add dyn Future: Unpin bounds to convert Pin<&mut &mut dyn Future> to Pin<&mut dyn Future>.

Solution
Change DynFuture from &'a mut dyn Future<Output = T> to &'a mut (dyn Future<Output = T> + Unpin).
https://github.com/AldaronLau/pasts/blob/675bd309d609111fac52889602e31c9609e7f2ea/src/dyn_future.rs#L14

Additional context
I have fixed a similar bug on tokio in the past: tokio-rs/tokio#2612
Also, #2, previously reported by @udoprog and already fixed by @AldaronLau, seems to be the same problem as this.

Add temporary dependency on futures-core

The way pasts currently uses the Future trait is better suited for a Stream trait, Stream

Will eventually be able to go back to zero dependencies once Stream/AsyncIterator lands in the Rust core library.

Complete Test Suite

Make some unit tests to test all of the Pasts' public API (and verify test coverage in CI).

Replace `Notify` usage with lending `AsyncIterator`

I no longer think the benefits of having Notify as a separate trait are worth the trade-off, since in practice, most Notifys have a point where they could end. Additionally, when using pasts I have found the need for what is essentially a lending async iterator (for updates to the wavy crate - currently wavy uses unsafe code to "get around" this limitation).

Since AsyncIterator is not stable in std yet, this will have to be redefined in pasts, with a compatibility feature that will currently depend on nightly, and one for Stream compatibility.

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=775ff0afbe5e28a0e48403b9145dcef6

pub trait AsyncIterator {
    type Item<'a>;

    fn poll_next<'a>(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item<'a>>>;

    // Return type should be switched out for public type with private constructor
    // 
    // Choosing to take as `Pin` to allow `.next()` to be called in more places,
    // although often more verbose than requiring `Unpin` (may also add `next_unpinned()`)
    fn next<'a>(mut self: Pin<&mut Self>) -> impl Future<Output = Option<Self::Item<'a>>> + '_ {
        std::future::poll_fn(move |cx| self.as_mut().poll_next(cx))
    }
}

Rather than treating an async iterator as a stream, and having another sink type, those concepts build on what an async iterator is (similar to wavy's current design, returning fon's streams and sinks on Ready). I'll add an example later.

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.