Skip to main content

FlowHandle

Struct FlowHandle 

Source
pub struct FlowHandle { /* private fields */ }
Expand description

A reference to a spawned flow, returned by super::runtime::Runtime::spawn.

Holding a FlowHandle does not keep the flow alive — it is a way to (a) read its FlowId for addressing with Send, and (b) block the calling native thread until it finishes via FlowHandle::join. Dropping without joining is fine (fire-and-forget).

Implementations§

Source§

impl FlowHandle

Source

pub fn id(&self) -> FlowId

Source

pub fn join(self) -> FlowOutcome

Block the current (native) thread until the flow terminates. Never call from inside a worker / from bytecode.

Examples found in repository?
examples/ping_pong.rs (line 36)
9fn main() {
10    let chunk = samples::ping_pong();
11    let rt = match Runtime::with_natives_and_config(
12        chunk,
13        std_native_table(),
14        RuntimeConfig {
15            workers: 1,
16            quantum: 10_000,
17        },
18    ) {
19        Ok(rt) => rt,
20        Err(e) => {
21            eprintln!("runtime: {e}");
22            std::process::exit(1);
23        }
24    };
25    let Some(main) = rt.function_index("main") else {
26        eprintln!("missing main");
27        std::process::exit(1);
28    };
29    let handle = match rt.spawn(main, &[]) {
30        Ok(h) => h,
31        Err(e) => {
32            eprintln!("spawn: {e}");
33            std::process::exit(1);
34        }
35    };
36    let outcome = handle.join();
37    let metrics = rt.metrics();
38    rt.shutdown();
39
40    match outcome {
41        FlowOutcome::Completed(Value::Int(2)) => {
42            println!("pong replied 2 (Atomic Hop)");
43            println!("{metrics}");
44        }
45        other => {
46            eprintln!("unexpected {other:?}");
47            std::process::exit(1);
48        }
49    }
50}
More examples
Hide additional examples
examples/atomic_actors.rs (line 48)
21fn main() {
22    let chunk = samples::atomic_request_reply();
23    let rt = match Runtime::with_natives_and_config(
24        chunk,
25        std_native_table(),
26        RuntimeConfig {
27            workers: 2,
28            quantum: 10_000,
29        },
30    ) {
31        Ok(rt) => rt,
32        Err(e) => {
33            eprintln!("runtime: {e}");
34            std::process::exit(1);
35        }
36    };
37    let Some(main) = rt.function_index("main") else {
38        eprintln!("missing main");
39        std::process::exit(1);
40    };
41    let handle = match rt.spawn(main, &[]) {
42        Ok(h) => h,
43        Err(e) => {
44            eprintln!("spawn: {e}");
45            std::process::exit(1);
46        }
47    };
48    let outcome = handle.join();
49    let metrics = rt.metrics();
50    rt.shutdown();
51
52    match outcome {
53        FlowOutcome::Completed(Value::Int(42)) => {
54            println!("atomic request-reply ok: payload=42");
55            println!("{metrics}");
56        }
57        other => {
58            eprintln!("unexpected {other:?}");
59            std::process::exit(1);
60        }
61    }
62}
examples/throughput.rs (line 60)
19fn main() {
20    let n: u32 = std::env::args()
21        .nth(1)
22        .and_then(|s| s.parse().ok())
23        .unwrap_or(50_000);
24
25    let workers = std::thread::available_parallelism()
26        .map(|p| p.get())
27        .unwrap_or(1);
28
29    let rt = match Runtime::with_config(
30        trivial_chunk(),
31        RuntimeConfig {
32            workers,
33            quantum: 10_000,
34        },
35    ) {
36        Ok(rt) => rt,
37        Err(e) => {
38            eprintln!("runtime: {e}");
39            std::process::exit(1);
40        }
41    };
42    let Some(worker_fn) = rt.function_index("worker") else {
43        eprintln!("missing worker");
44        std::process::exit(1);
45    };
46
47    let start = Instant::now();
48    let mut handles = Vec::with_capacity(n as usize);
49    for _ in 0..n {
50        match rt.spawn(worker_fn, &[]) {
51            Ok(h) => handles.push(h),
52            Err(e) => {
53                eprintln!("spawn: {e}");
54                std::process::exit(1);
55            }
56        }
57    }
58    let mut ok = 0u32;
59    for h in handles {
60        if matches!(h.join(), FlowOutcome::Completed(Value::Int(1))) {
61            ok += 1;
62        }
63    }
64    let elapsed = start.elapsed();
65    let metrics = rt.metrics();
66    rt.shutdown();
67
68    let secs = elapsed.as_secs_f64().max(1e-9);
69    println!("processes={ok}/{n}");
70    println!("workers={workers}");
71    println!("elapsed_ms={:.2}", elapsed.as_secs_f64() * 1000.0);
72    println!("spawns_per_sec={:.0}", ok as f64 / secs);
73    println!("{metrics}");
74}

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.