#hub #actor-framework #spawn #proc-macro

macro bin derive_hub

A proc-macro for a simple actor framework

1 unstable release

0.1.0 Oct 2, 2023

#976 in Procedural macros

MIT/Apache

13KB
123 lines

derive_hub

A simple actor hub that generates the following code.


       #[derive(::derive_builder::Builder, ::std::fmt::Debug)]
       pub struct #hub_name {
           #[builder(setter(skip))]
           workers: ::std::vec::Vec<tokio_util::sync::CancellationToken>,
           #(#field_declarations,)*
       }

       impl ::std::ops::Drop for #hub_name {
           fn drop(&mut self) {
               self.shutdown();
           }
       }

       impl #hub_name {
           /// Spawns a given number of workers threads.
           ///
           #[inline]
           pub fn spawn(&mut self, worker_count: usize) -> ::std::vec::Vec<::tokio::task::JoinHandle<()>> {
               assert!(worker_count > 0, "Worker count has to be greater than zero, but got {}", worker_count);
               (0..worker_count)
                   .map(|_| {
                       let token = ::tokio_util::sync::CancellationToken::new();
                       self.workers.push(token.clone());
                       let item = #item_builder::default()
                           #(#inits)*
                           .build()
                           .expect(concat!("Should be able to build ", stringify!(#hub_name), "."));
                       ::tokio::spawn(async move {
                           item.run(token).await;
                       })
                   })
                   .collect::<Vec<_>>()
           }

           /// Shutdown hub.
           ///
           #[inline]
           pub fn shutdown(&self) {
               for worker in &self.workers {
                   worker.cancel();
               }
           }
       }

Inert Attributes:

  • #[hub(skip)] - Should be used in conjunction with default functions of the builder of the agent struct.

Preconditions:

  • Crates that have to be installed: Tikio, tokio-util, derive-builder.
  • The members of the struct should be inside an Arc, which will be cloned by the hub when spawning.
  • Naturally, all members have to be syn and send.
  • The struct has to implemnet derive_builder::Builder
  • The struct that has the derive attribute has to have a method of same signature as this example:
pub async fn run(self, flag: tokio_util::sync::CancellationToken) {
       loop {
           tokio::select! {
               biased;
               _ = flag.cancelled() => {
                   /* Wind down actor */
                   break;
               }
               item = self.foo.pop() => {
                   /* Do something important */
               }
               item = self.bar.pop() => {
                   /* Do something important */
               }
               item = self.baz.pop() => {
                   /* Do something important */
               }
           };
       }
   }

Recommendations.

  • Fields should ideally contain a deadqueue::Queue.

Dependencies

~0.8–1.2MB
~27K SLoC