zero_pool/macros.rs
1/// Create a task parameter struct with automatic constructor
2///
3/// This macro generates a struct with the specified fields and a `new` method
4/// that takes all fields as parameters in declaration order.
5///
6/// # Examples
7/// ```rust
8/// use zero_pool::zp_task_params;
9///
10/// zp_task_params! {
11/// MyTask {
12/// input: u64,
13/// iterations: usize,
14/// result: *mut u64,
15/// }
16/// }
17///
18/// let mut result = 0u64;
19/// let task = MyTask::new(42, 1000, &mut result);
20/// ```
21#[macro_export]
22macro_rules! zp_task_params {
23 ($struct_name:ident { $($field:ident: $field_type:ty),* $(,)? }) => {
24 pub struct $struct_name {
25 $(pub $field: $field_type,)*
26 }
27
28 impl $struct_name {
29 pub fn new($($field: $field_type),*) -> Self {
30 Self {
31 $($field,)*
32 }
33 }
34 }
35 };
36}
37
38/// Define a task function with automatic parameter dereferencing
39///
40/// This macro creates a task function that safely dereferences the raw
41/// parameter pointer to the specified type, allowing safe access to fields.
42///
43/// # Examples
44/// ```rust
45/// use zero_pool::{zp_define_task_fn, zp_task_params, zp_write};
46///
47/// zp_task_params! {
48/// ComputeTask {
49/// iterations: usize,
50/// result: *mut u64,
51/// }
52/// }
53///
54/// zp_define_task_fn!(compute_task, ComputeTask, |params| {
55/// let mut sum = 0u64;
56/// for i in 0..params.iterations {
57/// sum = sum.wrapping_add(i as u64);
58/// }
59/// zp_write!(params.result, sum);
60/// });
61/// ```
62#[macro_export]
63macro_rules! zp_define_task_fn {
64 ($fn_name:ident, $param_type:ty, |$params:ident| $body:block) => {
65 fn $fn_name(raw_params: $crate::TaskParamPointer) {
66 let $params = unsafe { &*(raw_params as *const $param_type) };
67 $body
68 }
69 };
70}
71
72/// Write a result to a raw pointer (eliminates explicit unsafe blocks)
73///
74/// This macro wraps the unsafe pointer dereference, making task code cleaner.
75///
76/// # Examples
77/// ```rust
78/// use zero_pool::{zp_write, zp_define_task_fn, zp_task_params};
79///
80/// zp_task_params! {
81/// MyTask { value: u64, result: *mut u64 }
82/// }
83///
84/// zp_define_task_fn!(my_task, MyTask, |params| {
85/// let result = 42u64;
86/// zp_write!(params.result, result);
87/// });
88/// ```
89#[macro_export]
90macro_rules! zp_write {
91 ($result_ptr:expr, $value:expr) => {
92 unsafe {
93 *$result_ptr = $value;
94 }
95 };
96}
97
98/// Write a value to a specific index in a collection via raw pointer
99///
100/// This macro eliminates explicit unsafe blocks when writing to indexed collections.
101///
102/// # Examples
103/// ```rust
104/// use zero_pool::{zp_write_indexed, zp_define_task_fn, zp_task_params};
105///
106/// zp_task_params! {
107/// BatchTask { index: usize, results: *mut Vec<u64> }
108/// }
109///
110/// zp_define_task_fn!(batch_task, BatchTask, |params| {
111/// let sum = 42u64;
112/// zp_write_indexed!(params.results, params.index, sum);
113/// });
114/// ```
115#[macro_export]
116macro_rules! zp_write_indexed {
117 ($collection_ptr:expr, $index:expr, $value:expr) => {
118 unsafe {
119 (&mut (*$collection_ptr))[$index] = $value;
120 }
121 };
122}
123
124/// Submit a batch of mixed task types with type safety
125///
126/// This macro allows submitting tasks of different types in a single batch,
127/// handling the type erasure automatically.
128///
129/// # Examples
130/// ```rust
131/// use zero_pool::{ZeroPool, zp_submit_batch_mixed, zp_task_params, zp_define_task_fn, zp_write};
132///
133/// zp_task_params! {
134/// Task1 { value: u64, result: *mut u64 }
135/// }
136/// zp_task_params! {
137/// Task2 { value: u64, result: *mut u64 }
138/// }
139///
140/// zp_define_task_fn!(task1_fn, Task1, |params| {
141/// zp_write!(params.result, params.value * 2);
142/// });
143/// zp_define_task_fn!(task2_fn, Task2, |params| {
144/// zp_write!(params.result, params.value * 3);
145/// });
146///
147/// let pool = ZeroPool::new();
148/// let mut result1 = 0u64;
149/// let mut result2 = 0u64;
150/// let task1 = Task1::new(5, &mut result1);
151/// let task2 = Task2::new(7, &mut result2);
152/// let future = zp_submit_batch_mixed!(pool, [
153/// (&task1, task1_fn),
154/// (&task2, task2_fn),
155/// ]);
156/// future.wait();
157/// ```
158#[macro_export]
159macro_rules! zp_submit_batch_mixed {
160 ($pool:expr, [$( ($params:expr, $task_fn:ident) ),* $(,)?]) => {{
161 let tasks: Vec<$crate::TaskItem> = vec![
162 $(
163 ($task_fn as $crate::TaskFnPointer, $params as *const _ as $crate::TaskParamPointer)
164 ),*
165 ];
166
167 $pool.submit_raw_task_batch(&tasks)
168 }};
169}