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