1use std::sync::Arc;
2use std::fmt;
3
4#[macro_export]
6macro_rules! rc {
7 ( $f:ident ) => { Box::new($f) };
8 ( $f:expr ) => { Box::new($f) };
9}
10
11#[macro_export]
13macro_rules! arc {
14 ( $f:ident ) => { ::std::sync::Arc::new(Box::new($f)) };
15 ( $f:expr ) => { ::std::sync::Arc::new(Box::new($f)) };
16}
17
18#[macro_export]
20macro_rules! box_fn {
21 ( $f:ident ) => { rc!($f) };
22 ( $f:expr ) => { rc!($f) };
23}
24
25#[macro_export]
28macro_rules! arc_fn {
29 ( $f:ident ) => { arc!($f) };
30 ( $f:expr ) => { arc!($f) };
31}
32
33#[macro_export]
36macro_rules! spawn_fn {
37 ( $f:expr ) => { ::std::thread::spawn($f)};
38 ( $f:ident, $( $arg:ident ),* ) => { {let v = $f.clone(); ::std::thread::spawn(move || {v($($arg),*)})}};
39 ( $f:expr, $( $arg:expr ),* ) => { ::std::thread::spawn(move || {$f($($arg),*)}) };
40}
41
42pub type BoxFn<T> = Box<T>;
45
46pub type ArcFn<T> = Arc<Box<T>>;
49
50#[cfg(test)]
51mod tests {
52 use std::thread;
53 use super::*;
54
55 #[test]
56 fn zero_arity_box_fn() {
57 let wrapped_prim = |i: u32| { println!("{}", i + 10) };
58 let wrapped_vec = |v: Vec<&str>| { println!("{:?}", v) };
59
60 let _t = box_fn!(||{println!("Neat!")});
61 let _c = box_fn!(||{println!("Neat!")});
62
63 box_fn!(||{println!("Neat!")})();
64 box_fn!(||{wrapped_prim(10)})();
65 box_fn!(||{wrapped_vec(vec!["nice", "cool"])})();
66 }
67
68 #[test]
69 fn one_arity_box_fn() {
70 box_fn!(|a: &str|{println!("{}", a)})("Awesome!");
71 box_fn!(|i: u32| {println!("{}", i + 10)})(10);
72 box_fn!(|v: Vec<&str>| { println!("{:?}", v) })(vec!["nice", "cool"]);
73 }
74
75 #[test]
76 fn pass_named_box_fn() {
77 let wrapped_prim = |i: u32| { println!("{}", i + 10) };
78 let wrapped_vec = |v: Vec<&str>| { println!("{:?}", v) };
79
80 box_fn!(wrapped_prim)(10);
81 box_fn!(wrapped_vec)(vec!["nice", "cool"])
82 }
83
84 #[test]
85 fn pass_function_box_fn() {
86 fn func(s: &str) { println!("{}", s)}
87
88 box_fn!(func)("Wow!");
89 }
90
91 #[test]
92 fn in_struct_box_fn() {
93 type T = BoxFn<Fn(&str) -> String>;
94
95 struct F {
96 c: T
97 }
98
99 let c: T = box_fn!(|s: &str| -> String {s.to_string()});
100
101 let mut f = F { c };
102
103 f.c = box_fn!(
104 |d: &str| -> String {"reassign once".to_string()}
105 );
106
107 f.c = box_fn!(
108 |_: &str| {"and again".to_string()}
109 );
110 }
111
112
113 #[test]
114 fn in_struct_arc_fn() {
115 type T = ArcFn<Fn(&str) -> String>;
116
117 #[derive(Clone)]
118 struct F {
119 c: T
120 }
121
122 let c: T = arc_fn!(|s: &str| -> String {s.to_string()});
123
124 let mut f = F { c };
125
126 f.c = arc_fn!(
127 |d: &str| -> String {"reassign once".to_string()}
128 );
129
130 f.c = arc_fn!(
131 |_: &str| {"and again".to_string()}
132 );
133 }
134
135 #[test]
136 fn multithreading_box_fn() {
137 let eg = box_fn!(|x: i32| -> i32 {x + 2});
138
139 let mut v1 = Vec::new();
140 for i in 0..1000 {
141 let cl = eg.clone();
142 v1.push(thread::spawn(move ||{cl(i)})); }
145
146 for res in v1.into_iter() {
147 res.join();
148 }
149 }
150
151 #[test]
152 fn multithreading_spawn_fn() {
153 let eg = box_fn!(|x: i32| -> i32 {x + 2});
154 let also = box_fn!(|x: i32, y: i32| -> i32 {x + y});
155
156 let mut v1 = Vec::new();
157 for i1 in 0..10000 {
158 let i2 = i1 + 10;
159 v1.push(spawn_fn!(eg, i1));
160 v1.push(spawn_fn!(also, i1, i2)); }
162 v1.push(spawn_fn!(||{println!("accepts closures to run in their own thread!"); 1}));
163
164 for res in v1.into_iter() {
165 res.join();
166 }
167 }
168}