@@ -22,6 +22,101 @@ A high-level pitch of the feature:
2222* The ` async ` usage in Rust is already well established technique that is
2323 adopted by many crates, including those with highest usage
2424
25+
26+ ### Introduction to async in context of iceoryx2
27+
28+ The Rust ` async ` APIs are build with the help of usage of compiler. At the end
29+ ` async ` and ` await ` is just a syntactic sugar that is removed during ` HIR ` . In
30+ practice it means:
31+ * ` async fn abc() -> bool ` signature is turned into
32+ ` fn abc() -> impl core::future::Future<Output=bool> ` . This basically means
33+ each async fn is a anonymous type that implements ` core::future::Future `
34+ * ` await ` is turned be compiler into generated state machine that simply
35+ decompose to all states (continues and returns) in function using ` Future `
36+ trait API. To have small example, below code:
37+ ``` rust
38+
39+ async fn some_other_async_fn () {
40+ println! (" Test" );
41+ }
42+
43+ async fn abc () -> bool {
44+
45+ some_other_async_fn (). await
46+
47+ true
48+ }
49+ ```
50+
51+ Will be turned into (pseudocode):
52+ ``` rust
53+
54+ fn some_other_async_fn () -> impl core :: future :: Future <Output = ()> {
55+ println! (" Test" );
56+ core :: task :: Poll :: Ready (())
57+ }
58+
59+ fn abc () -> impl core :: future :: Future <Output = bool > {
60+
61+ let future = some_other_async_fn ();
62+ let mut _hidden_satte = 0 ;
63+
64+ if _hidden_satte == 0 {
65+ match future . poll (... ) {
66+ core :: task :: Poll :: Pending => return Pending
67+ core :: task :: Poll :: Ready (_ ) => {
68+ ///
69+ _hidden_satte = 1 ;
70+ }
71+ }
72+ }
73+
74+ /// And for next .awaits, continue the idea
75+ /// Compiler will ofc generate something totally different but thats the idea behind
76+
77+ true
78+ }
79+
80+ ```
81+
82+ At the end, Rust SIG has decided to provide interface (traits) and compiler
83+ syntactic sugar to support ` async ` but left the ` runtime ` being external needed
84+ component that is not part of language.
85+
86+ #### Brief simplification how does Futures works
87+ Once creating own ` Future ` implementation using ` core::future::Future ` trait You
88+ are provided the ` Context ` that holds the ` Waker ` . The implementer
89+ responsibility for future is to return either ` core::task::Poll::Pending ` once
90+ Your Future is not ready yet or ` core::task::Poll::Ready(_) ` once Future is
91+ done wih work. In the first case, once You detected you are not ready, Your
92+ obligation is to:
93+ * take ` Waker ` and store it somewhere
94+ * return ` core::task::Poll::Pending ` (at this moment runtime will remove You
95+ from processing queue and will not process until woken)
96+ * call ` Waker::wake* ` API once You know your Future can progress
97+
98+ After telling runtime via ` Waker::wake* ` that you are ready, ` runtime ` will
99+ bring You back to some of its workers and again will execute ` Future::poll ` to
100+ check Your progress.
101+
102+ ### Connection to iceoryx2 messaging patterns
103+
104+ #### Events
105+ Nothing to add, blocking API needs async versions
106+
107+ #### Publisher Subscriber
108+ Here in async world (and even in non async really) as a user expectation would
109+ be that I can react once a new ` sample ` is produced so that I don't have to poll
110+ for it, instead simply ` await ` it.
111+
112+ #### Request Response
113+ Here in async world (and even in non async really) as a user expectation would
114+ be that there is one entity that is a "Server" (the one that hosts method and
115+ produces responses) and there are clients that do requests. Due to this,
116+ ` request-response ` would need ` async ` API to only act once there is request and
117+ once there is reply for it.
118+
119+
25120## Requirements
26121
27122* ** R1: Async API look and feel** \* The new ` async ` API shall provide the same
@@ -201,3 +296,83 @@ guarantee any of above.
201296** Results:**
202297
203298* PubSub API will have ` async ` API available
299+
300+
301+
302+ ## Extended examples
303+
304+ ### Pub Sub pseudo code example
305+
306+ > NOTE: ` async main ` is the extension provided by runtimes, it simply wraps
307+ > regular main into creation of runtime and put this into execution
308+
309+ ** Process 1**
310+ ``` rust
311+ async fn main () {
312+ let node = NodeBuilder :: new (). create :: <ipc_threadsafe :: Service >(). unwrap ();
313+
314+ let event = node
315+ . service_builder (& " MyEventName" . try_into (). unwrap ())
316+ . event ()
317+ . open_or_create ()
318+ . unwrap ();
319+
320+ let listener = event . listener_builder (). create_async (). unwrap ();
321+ let listener2 = event . listener_builder (). create_async (). unwrap ();
322+
323+ let task1_handle = spawn (async move {
324+ println! (" Awaiting for Iceoryx event in batches while doing something else ..." );
325+ loop {
326+
327+ listener
328+ . wait_all (& mut | event_id | {
329+ print! (" Received Iceoryx event: {:?}\ n" , event_id );
330+ })
331+ . await // During this not being ready, worker can do any other work
332+ . unwrap ();
333+ }
334+ });
335+
336+
337+ spawn (async move {
338+
339+ // Some logic
340+ // ..
341+
342+ // now I need sample in this place due to my logic, so I simply 'await' it and once
343+ // I have a sample, this code will continue executing further
344+ let sample_res = listener2 . wait (). await ; // During this not being ready, worker can do any other work
345+
346+ // Process sample
347+
348+ // ..
349+
350+ });
351+
352+
353+
354+ // Optionally You may wait until task finishes
355+ task1_handle . await . unwrap (); // During this not being ready, worker can do any other work
356+ }
357+ ```
358+
359+ ** Process 2**
360+ ``` rust
361+ async fn main () {
362+ let node = NodeBuilder :: new (). create :: <ipc_threadsafe :: Service >(). unwrap ();
363+
364+ let event = node
365+ . service_builder (& " MyEventName" . try_into (). unwrap ())
366+ . event ()
367+ . open_or_create ()
368+ . unwrap ();
369+
370+ let notifier = event . notifier_builder (). create_async (). unwrap ();
371+ println! (" Awaiting for Iceoryx event in batches while doing something else ..." );
372+
373+ loop {
374+ notifier . notify ();
375+ sleep (100 ). await ; // During that sleep, worker can be doing any other work ;)
376+ }
377+ }
378+ ```
0 commit comments