A single-threaded executor for deferred async code for games.

Overview

cosync

docs.rs Crates.io Crates.io

This crate provides a single-threaded, sequential, parameterized async runtime. In other words, this creates coroutines, specifically targeting video game logic, though cosync is suitable for creating any sequences of directions which take time.

Here's a basic Cosync example:

use cosync::{Cosync, CosyncInput};

fn main() {
    // the type parameter is the *value* which other functions will get.
    let mut cosync: Cosync<i32> = Cosync::new();
    let example_move = 20;

    // there are a few ways to queue tasks, but here's a simple one:
    cosync.queue(move |mut input: CosyncInput<i32>| async move {
        // set our input to `example_move`...
        *input.get() = example_move;
    });

    let mut value = 0;
    cosync.run_until_stall(&mut value);

    // okay, we ran our future, and since it has no awaits, we know
    // it will have completed!
    assert_eq!(value, example_move);
}

Cosync is not multithreaded, nor parallel -- it works entirely sequentially. Think of it as a useful way of expressing code that is multistaged and takes time to complete, that you want to do later. Moving cameras, staging actors, and performing animations often work well with Cosync. Loading asset files, doing mathematical computations, or doing IO should be done by more easily multithreaded runtimes such as switchyard.

This crate exposes two methods for driving the runtime: run_until_stall and run_blocking. You generally want run_until_stall, which attempts process as much of the queue as it can, until it cannot (ie, a future returns Poll::Pending), at which point control is returned to the caller.

There are three ways to make new tasks. First, the Cosync struct itself has a queue method on it. Secondly, each task gets a CosyncInput as a parameter, which has get (to get access to your &mut T) and queue to queue another task (which is at the end of the queue, not necessarily after the task which added it). Lastly, you can create a CosyncQueueHandle with Cosync::create_queue_handle which is Send and can be given to other threads to create new tasks for the Cosync.

This crate depends on only std. It is in an early state of development, but is in production ready state right now.

You might also like...
A framework for modding and instrumenting games.

me3 A framework for modifying and instrumenting games. Explore the docs » Report Bug · Request Feature About The Project Built With Getting Started Pr

A framework for building adventure games in Bevy.

Bevy_adventure A framework for building 3d adventure games in Bevy. preview.mp4 Features Interactive trait is the backbone of the framework, allowing

Bevy virtual Joystick for mobile games (Works with mouse on desktop)
Bevy virtual Joystick for mobile games (Works with mouse on desktop)

Bevy Virtual Joystick Create and use a Virtual Joystick in a UI for bevy Game Engine. Versions Aviable and compatible versions bevy VirtualJoystick 0.

Explicitly set sprite layers for sprites in Bevy games.
Explicitly set sprite layers for sprites in Bevy games.

extol_sprite_layer lets you specify the drawing order for sprites in your Bevy game using a separate component rather than via the z-coordinate of you

Highly customizable splash screen library for Bevy games.

bevy_intro_screen This is a versatile Bevy library designed to create engaging and customizable introductory screens for your game. Initially conceive

Hierarchical Task Network Planning deeply integrated with bevy, which I use in my games :P

Note that CI currently tests against a matrix of (windows, mac, linux) * (toolchain stable, nightly) * (cargo build, test, clippy), which ensures vali

Bevy plugin for a simple single-line text input widget.
Bevy plugin for a simple single-line text input widget.

bevy_simple_text_input An unambitious single-line text input widget for bevy_ui. Usage See examples/basic.rs. Alternatives If you need more features,

A nine slice/patch plugin for bevy ui nodes as single component using a fragment shader.
A nine slice/patch plugin for bevy ui nodes as single component using a fragment shader.

Bevy nine slice/patch Material Plugin Quick and easy auto-scaling nine slice/patch material for bevy ui nodes implemented as Fragment Shader. Features

A simple asynchronous runtime for executing async coroutines in the bevy engine.

Bevy Defer A simple asynchronous runtime for executing async coroutines. Motivation Async rust is incredible for modelling wait centric tasks like cor

Comments
  • Borrowed inputs to tasks

    Borrowed inputs to tasks

    I'm trying to store my coroutine in a heap-allocated struct (or just heap-allocate the coroutine) and pass borrowed inputs to it in run_until_stall.

    As far as I understand, this is not possible with the current API. The problem is the type parameter of Cosync. If my input has borrowed bits, I need a type parameter like:

    struct MyInput<'a> {
        borrowed_bit: &'a MyBorrowedData,
        other_stuff: OtherStuff,
    }
    

    That type parameter that propogates into all the references to Cosync:

    type MyCoro<'a> = Cosync<MyInput<'a>>;
    

    which means I can't heap-allocate MyCoro: 'static is the only lifetime I can pass to MyCoro, but that's the not lifetime as I will be passing stack-allocated borrowed values to run_until_stall.

    I'm not sure how to best solve this problem in Rust. I'm wondering if you know a workaround. To solve this at the API level we would need to somehow avoid the type parameter for the coroutine input in the Cosync type. However if we do that then I don't know how to implement the run_until_stall method as it needs to know the coroutine input type.

    Any thoughts on this?


    The actual use case: In an app (not a game) I have an event source. Whenever an event arrives my callback is called with & and &mut, and value arguments (passed by the event loop to my callback). This callback is practically a coroutine: it takes an input (event data), it may run an action (or yield a value), or wait for more input. cosyn makes it much simpler to implement than an hand-written coroutine as I need to implement a lot of states manually.

    The problem is the callback needs to be heap allocated and passed to the event loop and I don't have control over the event loop code to change this.

    opened by osa1 2
  • Multiple tasks within a single `Cosync`

    Multiple tasks within a single `Cosync`

    I have a use case that requires the following pattern to be possible with cosync:

    // Somewhere...
    
    // Task A
    cosync.queue(|| async {
        do_something().await;
        do_another_thing().await;
    });
    
    // Task B
    cosync.queue(|| async {
        do_something().await;
        do_another_thing().await;
    });
    
    // Elsewhere, every tick...
    cosync.run_until_stall(); // this would run both Task A and Task B until they stall
    

    As a practical example of what I am trying to do, imagine a UI that has multiple elements within it, all of which decide they want to move across the screen, and they run that tween through Cosync. I need them all to move across the screen at the same time, but each needs to have its own task.

    opened by imlazyeye 1
Owner
Jonathan Spira
Jonathan Spira
An ergonomic physics API for bevy games.

Heron An ergonomic physics API for 2d and 3d bevy games. (powered by rapier) How it looks like fn main() { App::build() .add_plugins(DefaultPlug

Jonathan Cornaz 313 Dec 16, 2022
A frontend to Assets purchased on Epic Games Store

Epic-Asset-Manager A frontend to Assets purchased on Epic Games Store Current Screenshot Install Arch Linux Use the AUR package Build flatpak meson _b

Acheta Games 202 Jan 3, 2023
A framework for making games using Macroquad.

Omegaquad A framework for making games using Macroquad. After writing maybe 5 games and finding myself always going to the previous project to copy-pa

null 14 Oct 13, 2022
Synchronize games from other platforms into your Steam library

BoilR Description This little tool will synchronize games from other platforms into your Steam library, using the Steam Shortcuts feature. The goal is

Philip Kristoffersen 823 Jan 9, 2023
A simple camera for properly displaying tile-based low resolution pixel perfect 2D games in bevy.

Bevy Tiled Camera A simple camera for properly displaying low resolution pixel perfect 2D games in bevy. The camera will adjust the viewport to scale

sark 10 Oct 5, 2022
A Rust promise for games and immediate mode GUIs

⌛ poll-promise A Rust promise for games and immediate mode GUIs Description poll-promise is a Rust crate for polling the result of a concurrent (e.g.

Embark 82 Dec 17, 2022
Using USBPcap to side-step anticheat in games, in order to reroute rumble packets to sex toys via The Buttplug Sex Toy Control Library

Using USBPcap to side-step anticheat in games, in order to reroute rumble packets to sex toys via The Buttplug Sex Toy Control Library.

qDot 23 Jan 3, 2023
Wein2D.js bindings for creating browser games in Rust using WebAssembly.

Wein2D.js-WASM Wein2D.js bindings for creating browser games in Rust using WebAssembly. Wein2D.js-WASM requires Wein2d.js to be loaded in the same doc

DevTaube 1 Apr 14, 2022
Cross-platform (including wasm) persistent key value store plugin for rust games/apps

bevy_pkv bevy_pkv is a cross-platform persistent key value store for rust apps. Use it for storing things like settings, save games etc. Currently, it

Johan Klokkhammer Helsing 25 Jan 9, 2023
A sandbox library for making FAST voxel games

voxelize WIP A well-optimized web-based voxel engine. Development Before starting, make sure to install the following: rust node.js cargo-watch # clon

Ian Huang (Shaoru) 146 Dec 30, 2022