4 releases
0.2.3 | Jan 31, 2024 |
---|---|
0.2.2 | Jan 29, 2024 |
0.2.1 | Jan 29, 2024 |
0.2.0 | Jan 29, 2024 |
#9 in #wrapped
28 downloads per month
25KB
336 lines
Tokiactor
About Tokiactor
tokiactor is a minimized implementation of actor
pattern based on tokio
runtime. No concepts like or System
or Context
involved, just Message
Handle
and Actor
.
In tokiactor
, Actor
is a wrapped function, sync
ort async
.
sync
function will be executed in multiple system threadsasync
function will be executed intokio
green thread asynchronously.
Large batch tasks like processing thousands of pictures can be done in parallel by leveraging buffered futures::StreamExt
trait from crate futures
.
Installation
Add tokiactor
to Cargo.toml
[dependencies]
tokiactor = "*"
tokiactor
needs tokio
to make things work.
Getting start
Following code will create Adder
actor, then, actor spawned in Handle
, Adder
will be called thru Handle::handle
method asynchronously.
use tokio;
use tokiactor::*;
let rt = tokio::runtime::Runtime::new().unwrap().block_on(
async move {
// create handle, then spawn a closure.
let handle = Handle::new(1).spawn(move |i: i32| i+ 41);
// call actor thru 'handle' method
assert_eq!(handle.handle(1).await, 42);
}
);
or, we can create Actor
from async
Closure
:
use tokio;
use tokiactor::*;
let rt = tokio::runtime::Runtime::new().unwrap().block_on(
async move {
let handle = Handle::new(1).spawn_tokio(move |i: i32| async move {i + 41});
assert_eq!(handle.handle(1).await, 42);
}
);
or, create Actor
from blocking fn
, then run Actor
in parallel
use tokio;
use tokiactor::*;
use futures::StreamExt;
fn adder_fn(i: i32) -> i32 {
std::thread::sleep(std::time::Duration::from_secs(1));
i+ 41
}
let rt = tokio::runtime::Runtime::new().unwrap().block_on(
async move {
let handle = Handle::new(10).spawn_n(10, adder_fn);
let results = futures::stream::iter((0..10))
.map(|i| handle.handle(i))
.buffered(10)
.collect::<Vec<_>>().await;
assert_eq!(results[9], 50)
}
);
Actor spawn
There are different ways to spawn an Actor
:
-
To spawn sync
Actor
-
Handle::spawn
: spawnActor
in1
background thread -
Handle::spawn_n
: spawnn
Actor
infn
implClone
inn
background threads.
-
-
To spawn async
Actor
Handle::spawn_tokio
: spawnActor
in background tokio thread, every asynchandle
will spawn an new tokio thread at background.
please check docs.rs for further infomation.
Handle
Handle
can be connected together, build another type of Handle
use tokio;
use tokiactor::*;
let rt = tokio::runtime::Runtime::new().unwrap().block_on(
async move {
let add = Handle::new(1).spawn(move |i: i32| i + 1);
let sub = Handle::new(1).spawn(move |i: i32| i - 1);
let div = Handle::new(1).spawn(move |i: i32| {
match i == 0 {
false => Some(10/i),
true => None
}
});
let mul = Handle::new(1).spawn(move |i: i32| i * 10);
let handle = add.then(sub).then(div).map(mul);
assert_eq!(handle.handle(0).await, None);
assert_eq!(handle.handle(2).await, Some(50));
}
);
Handle
can spawn both async
and sync
actor at the same time
use tokio;
use tokiactor::*;
let rt = tokio::runtime::Runtime::new().unwrap().block_on(
async move {
// Just a demo, don't do it in real code.
// spawn a fn
let handle = Handle::new(1).spawn(move |i: i32| i + 1);
// spawn an async fn
handle.spawn_tokio(move |i: i32| async move {i * 2});
}
);
Please check examples/icecream.rs
out for more complicated use case.
Dependencies
~4–11MB
~112K SLoC