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