@@ -914,12 +914,6 @@ zipt_impl! {
914
914
[ A B C D E F ] [ a b c d e f] ,
915
915
}
916
916
917
- #[ cfg( feature = "rayon" ) ]
918
- macro_rules! last_of {
919
- ( $q: ty) => { $q } ;
920
- ( $p: ty, $( $q: ty) ,+) => { last_of!( $( $q) ,+) } ;
921
- }
922
-
923
917
macro_rules! map_impl {
924
918
( $( [ $notlast: ident $( $p: ident) * ] , ) +) => {
925
919
$(
@@ -1016,14 +1010,6 @@ macro_rules! map_impl {
1016
1010
} ) . is_done( )
1017
1011
}
1018
1012
1019
- #[ cfg( feature = "rayon" ) ]
1020
- #[ allow( dead_code) ] // unused for the first of the Zip arities
1021
- /// Return a reference to the last producer
1022
- pub ( crate ) fn last_producer( & self ) -> & last_of!( $( $p) ,* ) {
1023
- let ( .., ref last) = & self . parts;
1024
- last
1025
- }
1026
-
1027
1013
expand_if!( @bool [ $notlast]
1028
1014
1029
1015
/// Include the producer `p` in the Zip.
@@ -1068,32 +1054,19 @@ macro_rules! map_impl {
1068
1054
/// inputs.
1069
1055
///
1070
1056
/// If all inputs are c- or f-order respectively, that is preserved in the output.
1071
- pub fn apply_collect<R >( self , mut f: impl FnMut ( $( $p:: Item , ) * ) -> R ) -> Array <R , D >
1057
+ pub fn apply_collect<R >( self , f: impl FnMut ( $( $p:: Item , ) * ) -> R ) -> Array <R , D >
1072
1058
{
1073
1059
// Make uninit result
1074
1060
let mut output = self . uninitalized_for_current_layout:: <R >( ) ;
1075
- if !std:: mem:: needs_drop:: <R >( ) {
1076
- // For elements with no drop glue, just overwrite into the array
1077
- self . apply_assign_into( & mut output, f) ;
1078
- } else {
1079
- // For generic elements, use a Partial to counts the number of filled elements,
1080
- // and can drop the right number of elements on unwinding
1081
- unsafe {
1082
- let mut output = output. raw_view_mut( ) . cast:: <R >( ) ;
1083
- let mut partial = Partial :: new( output. as_mut_ptr( ) ) ;
1084
- let partial_ref = & mut partial;
1085
- debug_assert!( output. is_contiguous( ) ) ;
1086
- debug_assert_eq!( output. layout( ) . tendency( ) >= 0 , self . layout_tendency >= 0 ) ;
1087
- self . and( output)
1088
- . apply( move |$( $p, ) * output_: * mut R | {
1089
- output_. write( f( $( $p ) ,* ) ) ;
1090
- partial_ref. len += 1 ;
1091
- } ) ;
1092
- partial. release_ownership( ) ;
1093
- }
1094
- }
1095
1061
1062
+ // Use partial to counts the number of filled elements, and can drop the right
1063
+ // number of elements on unwinding (if it happens during apply/collect).
1096
1064
unsafe {
1065
+ let output_view = output. raw_view_mut( ) . cast:: <R >( ) ;
1066
+ self . and( output_view)
1067
+ . collect_with_partial( f)
1068
+ . release_ownership( ) ;
1069
+
1097
1070
output. assume_init( )
1098
1071
}
1099
1072
}
@@ -1126,6 +1099,54 @@ macro_rules! map_impl {
1126
1099
}
1127
1100
}
1128
1101
1102
+ expand_if!( @bool [ $notlast]
1103
+ // For collect; Last producer is a RawViewMut
1104
+ #[ allow( non_snake_case) ]
1105
+ impl <D , PLast , R , $( $p) ,* > Zip <( $( $p, ) * PLast ) , D >
1106
+ where D : Dimension ,
1107
+ $( $p: NdProducer <Dim =D > , ) *
1108
+ PLast : NdProducer <Dim = D , Item = * mut R , Ptr = * mut R , Stride = isize >,
1109
+ {
1110
+ /// The inner workings of apply_collect and par_apply_collect
1111
+ ///
1112
+ /// Apply the function and collect the results into the output (last producer)
1113
+ /// which should be a raw array view; a Partial that owns the written
1114
+ /// elements is returned.
1115
+ ///
1116
+ /// Elements will be overwritten in place (in the sense of std::ptr::write).
1117
+ ///
1118
+ /// ## Safety
1119
+ ///
1120
+ /// The last producer is a RawArrayViewMut and must be safe to write into.
1121
+ /// The producer must be c- or f-contig and have the same layout tendency
1122
+ /// as the whole Zip.
1123
+ ///
1124
+ /// The returned Partial's proxy ownership of the elements must be handled,
1125
+ /// before the array the raw view points to realizes its ownership.
1126
+ pub ( crate ) unsafe fn collect_with_partial<F >( self , mut f: F ) -> Partial <R >
1127
+ where F : FnMut ( $( $p:: Item , ) * ) -> R
1128
+ {
1129
+ // Get the last producer; and make a Partial that aliases its data pointer
1130
+ let ( .., ref output) = & self . parts;
1131
+ debug_assert!( output. layout( ) . is( CORDER | FORDER ) ) ;
1132
+ debug_assert_eq!( output. layout( ) . tendency( ) >= 0 , self . layout_tendency >= 0 ) ;
1133
+ let mut partial = Partial :: new( output. as_ptr( ) ) ;
1134
+
1135
+ // Apply the mapping function on this zip
1136
+ // if we panic with unwinding; Partial will drop the written elements.
1137
+ let partial_len = & mut partial. len;
1138
+ self . apply( move |$( $p, ) * output_elem: * mut R | {
1139
+ output_elem. write( f( $( $p) ,* ) ) ;
1140
+ if std:: mem:: needs_drop:: <R >( ) {
1141
+ * partial_len += 1 ;
1142
+ }
1143
+ } ) ;
1144
+
1145
+ partial
1146
+ }
1147
+ }
1148
+ ) ;
1149
+
1129
1150
impl <D , $( $p) ,* > SplitPreference for Zip <( $( $p, ) * ) , D >
1130
1151
where D : Dimension ,
1131
1152
$( $p: NdProducer <Dim =D > , ) *
0 commit comments