silx_core/shared/utils/
mod.rs

1pub use crate::{
2    structs::{
3        archmod::archdata::{ ArchData, PinArchData, SlxData, },
4        cells::ctrl_message::{ MsgFromServant, SendToMaster, ReplyToServant, }, 
5        start_prod::{ StarterProducer, StarterProducerWithProcesses, StarterProducerWithFlow, },
6    },
7    traits::{
8        procell::{ ProcessProducer, ProcessInstance, }, 
9        filable::{ Filable, Filed, RecFiled, }, arch::ArchSized,
10    },
11    builder::{ ServantBuilder, ServantBuilderParameters, FiledStarter, Starter, },
12};
13
14#[macro_export]
15/// Generate an empty process instance
16/// * This is a macro helper for method `ProcessProducer::named_process(...)`
17/// 
18/// # Example:
19///
20/// ```text
21/// let producer = ProcessProducer::new(&send_to_master);
22/// let process_instance = produce!(producer);
23/// ```
24macro_rules! produce { ($prod: expr) => { 
25    $prod.named_process()
26} }
27
28#[macro_export]
29/// Generate an empty process instance with data
30/// * This is a macro helper for method `ProcessProducer::named_process_with_data(...)`
31/// 
32/// # Example:
33///
34/// ```text
35/// let producer = ProcessProducer::new(&send_to_master);
36/// let process_instance = produce_data!(producer,"My data");
37/// ```
38macro_rules! produce_data { ($prod: expr, $data: expr) => { 
39    $prod.named_process_with_data($data)
40} }
41
42#[macro_export]
43/// Generate a process instance for a given future
44/// * This is a macro helper for method `ProcessProducer::named_process_with_future(...)`
45/// 
46/// # Example:
47///
48/// ```text
49/// let producer = ProcessProducer::new(&send_to_master);
50/// let task = || { println!("task"); };
51/// let my_future = async { println!("async task"); };
52/// let process_instance = produce_future!(producer, {
53///     task();
54///     my_future.await;
55/// });
56/// ```
57macro_rules! produce_future { ($prod: expr, $code: block) => {
58        $prod.named_process_with_future(async move { $code std::future::pending::<()>().await })
59} }
60
61#[macro_export]
62/// Generate a process instance for a given future with data
63/// * This is a macro helper for method `ProcessProducer::named_process_with_future(...)`
64/// * Typically, data may be anything whith shared handles moved to the future
65/// 
66/// # Example:
67///
68/// ```text
69/// let producer = ProcessProducer::new(&send_to_master);
70/// let task = || { println!("task"); };
71/// let my_future = async { println!("async task"); };
72/// let process_instance = produce_data_future!(producer,"My data", {
73///     task();
74///     my_future.await;
75/// });
76/// ```
77macro_rules! produce_data_future { ($prod: expr, $data: expr, $code: block) => {
78    $prod.named_process_with_data_future($data, async move { $code std::future::pending::<()>().await })
79} }
80
81pub use produce;
82pub use produce_data;
83pub use produce_future;
84pub use produce_data_future;
85
86#[macro_export]
87/// Add a reply-to-query component of type 1 to the process producer
88/// * This is a macro helper for method `ProcessProducer::add_reply1(...)`
89/// 
90/// # Example:
91///
92/// ```text
93/// let mut producer = ProcessProducer::new(&send_to_master);
94/// let hello_channel = "IncrementQuery".to_string();
95/// produce_reply1!(producer, f64slx, hello_channel, data, {
96///     let mut rnum: Pin<&mut f64slx> = data.arch_mut().unwrap();
97///     *rnum += 1f64.slx();
98/// })?;
99/// ```
100macro_rules! produce_reply1 { ($prod: expr, $typ: ty, $chan: expr, $data: ident, $code: block $(,)?) => {
101    $prod.add_reply1::<$typ,_>(&$chan, move |$data| Box::pin(async move { $code }))
102} }
103
104#[macro_export]
105/// Add a reply-to-query component of type 2 to the process producer
106/// * This is a macro helper for method `ProcessProducer::add_reply2(...)`
107/// * Options and restrictions: 
108///    * the macro can move automatically variables which implement copy
109///         * then use the command without bracketed list of variables, or with empty bracket, like in:  
110///           `produce_reply2!(producer, U => V, channel_name, input, { ... code ...})`  
111///           `produce_reply2!([], producer, U => V, channel_name, input, { ... code ...})`
112///    * the macro cannot move automatically variables which implement clone but not copy
113///         * then use bracketed list of variables like in:  
114///           `produce_reply2!([var1, var2, ...], producer, U => V, channel_name, input, { ... code ...})`
115///    * the macro cannot move variables which do not implement clone
116/// 
117/// # Examples:
118/// ## Example with copiable data move:
119///
120/// ```text
121/// let mut producer = ProcessProducer::new(&send_to_master);
122/// let hello_channel = "HelloQuery".to_string();
123/// let choice = true;
124/// produce_reply2!(producer, String => String, hello_channel, data, {
125///     let astr = data.archive_ref().unwrap();
126///     let hs = if choice { format!("Hello {}", astr) } else  { format!("Good morning {}", astr) };
127///     hs.arch_sized().unwrap()
128/// })?;
129/// ```
130/// ## Example with clonable data move:
131///
132/// ```text
133/// let mut producer = ProcessProducer::new(&send_to_master);
134/// let hello_channel = "HelloQuery".to_string();
135/// let specific_greeting_0 = "Good morning".to_string();
136/// let specific_greeting_1 = "Good evening".to_string();
137/// let choice = 1;
138/// produce_reply2!([specific_greeting_0, specific_greeting_1], producer, String => String, hello_channel, data, {
139///     let astr = data.archive_ref().unwrap();
140///     let hs = match choice { 
141///         0 => format!("{specific_greeting_0} {}", astr),
142///         1 => format!("{specific_greeting_1} {}", astr),
143///         _ => format!("Hello {}", astr),
144///     };
145///     hs.arch_sized().unwrap()
146/// })?;
147/// ```
148macro_rules! produce_reply2 { 
149    ($prod: expr, $intyp: ty => $outyp: ty, $chan: expr, $data: ident, $code: block $(,)?) => (
150        produce_reply2!([], $prod, $intyp => $outyp, $chan, $data, $code)
151    );
152    ([$($I:ident),*], $prod: expr, $intyp: ty => $outyp: ty, $chan: expr, $data: ident, $code: block $(,)?) => (
153        $prod.add_reply2::<$intyp,$outyp,_>(&$chan, move |$data| { // invoke `add_reply2`
154            $(
155                let $I= $I.clone(); // clone the moved data
156            )*
157            Box::pin(async move { $code })
158        })
159    );
160}
161
162#[macro_export]
163/// Add a query component to the process producer, and get query sender and reply receiver
164/// * This is a macro helper for method `ProcessProducer::add_query(...)`
165/// 
166/// # Example:
167///
168/// ```text
169/// let mut producer = ProcessProducer::new(&send_to_master);
170/// let hello_channel = "HelloQuery".to_string();
171/// let capacity = Some(1);
172/// let (sender,receiver) = produce_query!(producer, String => String, hello_channel, capacity)?;
173/// ```
174macro_rules! produce_query { ($prod: expr, $intyp: ty => $outyp: ty, $chan: expr, $capa: expr $(,)?) => {
175    $prod.add_query::<$intyp,$outyp>(&$chan, $capa) 
176} }
177
178#[macro_export]
179/// Add an emit component to the process producer, and get emit sender
180/// * This is a macro helper for method `ProcessProducer::emit(...)`
181/// 
182/// # Example:
183///
184/// ```text
185/// let mut producer = ProcessProducer::new(&send_to_master);
186/// let wake_channel = "Wake".to_string();
187/// let capacity = Some(1);
188/// let sender = produce_emit!(producer, WakeSlx, wake_channel, capacity,)?;
189/// ```
190macro_rules! produce_emit { ($prod: expr, $typ: ty, $chan: expr, $capa: expr $(,)?) => { $prod.add_emit::<$typ>(&$chan, $capa) } }
191
192#[macro_export]
193/// Add an read component to the process producer, and get read receiver
194/// * This is a macro helper for method `ProcessProducer::read(...)`
195/// 
196/// # Example:
197///
198/// ```text
199/// let mut producer = ProcessProducer::new(&send_to_master);
200/// let wake_channel = "Wake".to_string();
201/// let capacity = Some(1);
202/// let reader = produce_read!(producer, WakeSlx, wake_channel, capacity,)?;
203/// ```
204macro_rules! produce_read { ($prod: expr, $typ: ty, $chan: expr, $capa: expr $(,)?) => { $prod.add_read::<$typ>(&$chan, $capa) } }
205
206#[macro_export]
207/// Add read by reference component to the process producer
208/// * This is a macro helper for method `ProcessProducer::add_ref_read(...)`
209/// * Macro `produce_ref_read` is quite similar to macro `produce_reply1` except that data is sent as non-mutable reference
210/// * Typical case of use of this component is to send a signal to an async process which will then react on this signal
211/// 
212/// # Example:
213///
214/// ```text
215/// let mut producer = ProcessProducer::new(&send_to_master);
216/// let warn_channel = "WarningChannel".to_string();
217/// produce_ref_read!(producer, String, warn_channel, data, {
218///     let astr = data.archive_ref().unwrap();
219///     println!("WARNING ABOUT SOMETHING WRONG:\n {}", astr);
220/// })?;
221/// ```
222macro_rules! produce_ref_read { ($prod: expr, $typ: ty, $chan: expr, $data: ident, $code: block $(,)?) => {
223    $prod.add_ref_read::<$typ,_>(&$chan, move |$data| Box::pin(async move { $code }))
224} }
225
226pub use produce_reply1;
227pub use produce_reply2;
228pub use produce_query;
229pub use produce_emit;
230pub use produce_read;
231pub use produce_ref_read;
232
233/// Asynchroneous process which is permanently pending
234pub async fn terminated() { std::future::pending::<()>().await }
235