@@ -683,6 +683,7 @@ where
683
683
/// Implementation based on replaying historical and new updates together.
684
684
mod history_replay {
685
685
686
+ use std:: mem:: ManuallyDrop ;
686
687
use :: difference:: Semigroup ;
687
688
use lattice:: Lattice ;
688
689
use trace:: Cursor ;
@@ -691,6 +692,13 @@ mod history_replay {
691
692
692
693
use super :: { PerKeyCompute , sort_dedup} ;
693
694
695
+ /// Clears and type erases a vector
696
+ fn vec_to_parts < T > ( v : Vec < T > ) -> ( * mut ( ) , usize ) {
697
+ let mut v = ManuallyDrop :: new ( v) ;
698
+ v. clear ( ) ;
699
+ ( v. as_mut_ptr ( ) as * mut ( ) , v. capacity ( ) )
700
+ }
701
+
694
702
/// The `HistoryReplayer` is a compute strategy based on moving through existing inputs, interesting times, etc in
695
703
/// time order, maintaining consolidated representations of updates with respect to future interesting times.
696
704
pub struct HistoryReplayer < ' a , V1 , V2 , T , R1 , R2 >
@@ -705,6 +713,11 @@ mod history_replay {
705
713
input_history : ValueHistory < ' a , V1 , T , R1 > ,
706
714
output_history : ValueHistory < ' a , V2 , T , R2 > ,
707
715
input_buffer : Vec < ( & ' a V1 , R1 ) > ,
716
+ // A type erased pointer and capacity for the temporary output buffer passed to `logic`.
717
+ // During `compute` the vector contains references to self which will get invalid as soon
718
+ // as compute returns. For this reason the temporary vector is always cleared before
719
+ // decomposing it back into its type erased parts
720
+ output_buffer_parts : ( * mut ( ) , usize ) ,
708
721
update_buffer : Vec < ( V2 , R2 ) > ,
709
722
output_produced : Vec < ( ( V2 , T ) , R2 ) > ,
710
723
synth_times : Vec < T > ,
@@ -727,6 +740,7 @@ mod history_replay {
727
740
input_history : ValueHistory :: new ( ) ,
728
741
output_history : ValueHistory :: new ( ) ,
729
742
input_buffer : Vec :: new ( ) ,
743
+ output_buffer_parts : vec_to_parts ( Vec :: < ( & V2 , R2 ) > :: new ( ) ) ,
730
744
update_buffer : Vec :: new ( ) ,
731
745
output_produced : Vec :: new ( ) ,
732
746
synth_times : Vec :: new ( ) ,
@@ -911,7 +925,16 @@ mod history_replay {
911
925
}
912
926
crate :: consolidation:: consolidate ( & mut self . input_buffer ) ;
913
927
914
- let mut output_buffer: Vec < ( & V2 , R2 ) > = Vec :: new ( ) ;
928
+ let ( ptr, cap) = self . output_buffer_parts ;
929
+ // SAFETY:
930
+ // * `ptr` is valid because is has been previously allocated by a Vec
931
+ // constructor parameterized with the same type argument
932
+ // * `len` and `cap` are valid because the vector is converted to parts
933
+ // only through `vec_to_parts` which clears the vector and gets its
934
+ // capacity
935
+ let mut output_buffer = unsafe {
936
+ Vec :: from_raw_parts ( ptr as * mut ( & V2 , R2 ) , 0 , cap)
937
+ } ;
915
938
meet. as_ref ( ) . map ( |meet| output_replay. advance_buffer_by ( & meet) ) ;
916
939
for & ( ( ref value, ref time) , ref diff) in output_replay. buffer ( ) . iter ( ) {
917
940
if time. less_equal ( & next_time) {
@@ -936,7 +959,7 @@ mod history_replay {
936
959
logic ( key, & self . input_buffer [ ..] , & mut output_buffer, & mut self . update_buffer ) ;
937
960
self . input_buffer . clear ( ) ;
938
961
}
939
- drop ( output_buffer) ;
962
+ self . output_buffer_parts = vec_to_parts ( output_buffer) ;
940
963
941
964
// output_replay.advance_buffer_by(&meet);
942
965
// for &((ref value, ref time), diff) in output_replay.buffer().iter() {
0 commit comments