1 unstable release

0.1.0 Apr 24, 2022

#49 in #tooling

MIT/Apache

47KB
995 lines

Async Object

This crate provides reference-counting wrappers with event support for using objects in asynchronous environment

The main purpose of the library is to provide foundation for my experimental GUI library WAG, but it's abstract enough to be used anywhere else.

Example

This code makes wrappers Background and WBackground for BackgroundImpl object. Internally they are just Arc<Rwlock> and Weak<Rwlock> plus tooling for access the Rwlock without blocking asyncronous job.

#[async_object_decl(pub Background, pub WBackground)]
struct BackgroundImpl {
   color: Color
}

#[async_object_impl(Background,  WBackground)]
impl BackgroundImpl {
   pub fn set_color(&mut this, color: Color) {
       this.color = color
   }
   pub fn get_color(&this) -> Color {
       this.color
   }
}

impl Background {
   pub fn new() -> Background {
       Background::create(BackgroundImpl { color: Color::White })
   }
}

The structures Background and WBackground will have these automatically generated proxy methods:

impl Background {
    pub fn set_color(...);
    pub fn get_golor() -> Color;
    async pub fn async_set_color(...);
    async pub fn async_get_color(...) -> Color
}

impl WBackground {
    pub fn set_color(...) -> Option<()>;
    pub fn get_golor() -> Option<Color>;
    async pub fn async_set_color(...) -> Option<()>;
    async pub fn async_get_color(...) -> Option<Color>
}

There is also event pub/sub support. For example:

enum ButtonEvent { Press, Release }

#[async_object_with_events_decl(pub Button, pub WButton)]
struct ButtonImpl {
}

#[async_object_impl(Button, WButton)]
impl ButtonImpl {
    async pub fn async_press(&mut self) {
        self.send_event(ButtonEvent::Press).await
    }
    pub fn press(&mut self) {
        let _ = self.send_event(ButtonEvent::Press)
    }
    pub fn events(&self) -> EventStream<ButtonEvent> {
        self.create_event_stream()
    }
}

Below is the code which changes background color when button is pressed

let pool = ThreadPool::builder().create().unwrap();
let button = Button::new();
let background = Background::new();

pool.spawn({
    let events = button.events();
    async move {
        // As soon as button is destroyed stream returns None
        while let Some(event) = events.next().await {
            // event has type Event<ButtonEvent>
            match *event.as_ref() {
                ButtonEvent::Pressed => background.set_color(Color::Red).await,
                ButtonEvent::Released => background.set_color(Color::White).await,
            }
        }
    }
});

Dependencies

~2.5MB
~53K SLoC