@@ -58,49 +58,57 @@ where
5858 ( a. unwrap ( ) , b. unwrap ( ) )
5959}
6060
61- /// Runs a list of blocks in parallel. The first block is executed immediately on
62- /// the current thread. Use that for the longest running block.
63- #[ macro_export]
64- macro_rules! parallel {
65- ( impl $fblock: block [ $( $c: expr, ) * ] [ $block: expr $( , $rest: expr) * ] ) => {
66- parallel!( impl $fblock [ $block, $( $c, ) * ] [ $( $rest) ,* ] )
67- } ;
68- ( impl $fblock: block [ $( $blocks: expr, ) * ] [ ] ) => {
69- $crate:: sync:: parallel_guard( |guard| {
70- $crate:: sync:: scope( |s| {
71- $(
72- let block = $crate:: sync:: FromDyn :: from( || $blocks) ;
73- s. spawn( move |_| {
74- guard. run( move || block. into_inner( ) ( ) ) ;
75- } ) ;
76- ) *
77- guard. run( || $fblock) ;
78- } ) ;
79- } ) ;
80- } ;
81- ( $fblock: block, $( $blocks: block) ,* ) => {
82- if $crate:: sync:: is_dyn_thread_safe( ) {
83- // Reverse the order of the later blocks since Rayon executes them in reverse order
84- // when using a single thread. This ensures the execution order matches that
85- // of a single threaded rustc.
86- parallel!( impl $fblock [ ] [ $( $blocks) ,* ] ) ;
87- } else {
88- $crate:: sync:: parallel_guard( |guard| {
89- guard. run( || $fblock) ;
90- $( guard. run( || $blocks) ; ) *
91- } ) ;
92- }
93- } ;
94- }
95-
96- // This function only works when `mode::is_dyn_thread_safe()`.
97- pub fn scope < ' scope , OP , R > ( op : OP ) -> R
61+ pub fn join4 < F0 , F1 , F2 , F3 , R0 , R1 , R2 , R3 > (
62+ oper0 : F0 ,
63+ oper1 : F1 ,
64+ oper2 : F2 ,
65+ oper3 : F3 ,
66+ ) -> ( R0 , R1 , R2 , R3 )
9867where
99- OP : FnOnce ( & rayon_core:: Scope < ' scope > ) -> R + DynSend ,
100- R : DynSend ,
68+ F0 : FnOnce ( ) -> R0 + DynSend ,
69+ F1 : FnOnce ( ) -> R1 + DynSend ,
70+ F2 : FnOnce ( ) -> R2 + DynSend ,
71+ F3 : FnOnce ( ) -> R3 + DynSend ,
72+ R0 : DynSend ,
73+ R1 : DynSend ,
74+ R2 : DynSend ,
75+ R3 : DynSend ,
10176{
102- let op = FromDyn :: from ( op) ;
103- rayon_core:: scope ( |s| FromDyn :: from ( op. into_inner ( ) ( s) ) ) . into_inner ( )
77+ if mode:: is_dyn_thread_safe ( ) {
78+ let oper0 = FromDyn :: from ( oper0) ;
79+ let oper1 = FromDyn :: from ( oper1) ;
80+ let oper2 = FromDyn :: from ( oper2) ;
81+ let oper3 = FromDyn :: from ( oper3) ;
82+ // Swap closures around because Chili executes second one on the current thread
83+ let ( r1, ( r2, ( r3, r0) ) ) = parallel_guard ( |guard| {
84+ let mut scope = chili:: Scope :: global ( ) ;
85+ scope. join_with_heartbeat_every :: < 1 , _ , _ , _ , _ > (
86+ move |_| guard. run ( move || FromDyn :: from ( oper1. into_inner ( ) ( ) ) ) ,
87+ move |scope| {
88+ scope. join_with_heartbeat_every :: < 1 , _ , _ , _ , _ > (
89+ move |_| guard. run ( move || FromDyn :: from ( oper2. into_inner ( ) ( ) ) ) ,
90+ move |scope| {
91+ scope. join_with_heartbeat_every :: < 1 , _ , _ , _ , _ > (
92+ move |_| guard. run ( move || FromDyn :: from ( oper3. into_inner ( ) ( ) ) ) ,
93+ move |_| guard. run ( move || FromDyn :: from ( oper0. into_inner ( ) ( ) ) ) ,
94+ )
95+ } ,
96+ )
97+ } ,
98+ )
99+ } ) ;
100+ (
101+ r0. unwrap ( ) . into_inner ( ) ,
102+ r1. unwrap ( ) . into_inner ( ) ,
103+ r2. unwrap ( ) . into_inner ( ) ,
104+ r3. unwrap ( ) . into_inner ( ) ,
105+ )
106+ } else {
107+ let ( r0, r1, r2, r3) = parallel_guard ( |guard| {
108+ ( guard. run ( oper0) , guard. run ( oper1) , guard. run ( oper2) , guard. run ( oper3) )
109+ } ) ;
110+ ( r0. unwrap ( ) , r1. unwrap ( ) , r2. unwrap ( ) , r3. unwrap ( ) )
111+ }
104112}
105113
106114#[ inline]
@@ -112,10 +120,11 @@ where
112120 if mode:: is_dyn_thread_safe ( ) {
113121 let oper_a = FromDyn :: from ( oper_a) ;
114122 let oper_b = FromDyn :: from ( oper_b) ;
115- let ( a, b) = parallel_guard ( |guard| {
116- rayon_core:: join (
117- move || guard. run ( move || FromDyn :: from ( oper_a. into_inner ( ) ( ) ) ) ,
118- move || guard. run ( move || FromDyn :: from ( oper_b. into_inner ( ) ( ) ) ) ,
123+ let ( b, a) = parallel_guard ( |guard| {
124+ chili:: Scope :: global ( ) . join_with_heartbeat_every :: < 1 , _ , _ , _ , _ > (
125+ // Swap arguments around because Chili executes second one on the current thread
126+ move |_| guard. run ( move || FromDyn :: from ( oper_b. into_inner ( ) ( ) ) ) ,
127+ move |_| guard. run ( move || FromDyn :: from ( oper_a. into_inner ( ) ( ) ) ) ,
119128 )
120129 } ) ;
121130 ( a. unwrap ( ) . into_inner ( ) , b. unwrap ( ) . into_inner ( ) )
@@ -136,6 +145,7 @@ fn par_slice<I: DynSend>(
136145 }
137146
138147 fn par_rec < I : DynSend , F : Fn ( & mut I ) + DynSync + DynSend > (
148+ scope : & mut chili:: Scope < ' _ > ,
139149 items : & mut [ I ] ,
140150 state : & State < ' _ , F > ,
141151 ) {
@@ -147,16 +157,21 @@ fn par_slice<I: DynSend>(
147157 let ( left, right) = items. split_at_mut ( items. len ( ) / 2 ) ;
148158 let mut left = state. for_each . derive ( left) ;
149159 let mut right = state. for_each . derive ( right) ;
150- rayon_core:: join ( move || par_rec ( * left, state) , move || par_rec ( * right, state) ) ;
160+ scope. join (
161+ // Swap arguments around because Chili executes second one on the current thread
162+ move |scope| par_rec ( scope, * right, state) ,
163+ move |scope| par_rec ( scope, * left, state) ,
164+ ) ;
151165 }
152166 }
153167
168+ let mut scope = chili:: Scope :: global ( ) ;
154169 let state = State {
155170 for_each : FromDyn :: from ( for_each) ,
156171 guard,
157172 group : std:: cmp:: max ( items. len ( ) / 128 , 1 ) ,
158173 } ;
159- par_rec ( items, & state)
174+ par_rec ( & mut scope , items, & state)
160175}
161176
162177pub fn par_for_each_in < I : DynSend , T : IntoIterator < Item = I > > (
0 commit comments