@@ -349,14 +349,13 @@ where
349
349
{
350
350
/// Fills all slots with the [`Default`] value.
351
351
fn from ( chunk : WriteChunkUninit < ' a , T > ) -> Self {
352
- for slot in chunk
353
- . first_slice
354
- . iter_mut ( )
355
- . chain ( chunk. second_slice . iter_mut ( ) )
356
- {
357
- unsafe {
358
- slot. as_mut_ptr ( ) . write ( Default :: default ( ) ) ;
359
- }
352
+ // NB: Using Iterator::chain() to iterate over both slices
353
+ // led to worse optimization (with rustc 1.57).
354
+ for slot in chunk. first_slice . iter_mut ( ) {
355
+ * slot = MaybeUninit :: new ( Default :: default ( ) ) ;
356
+ }
357
+ for slot in chunk. second_slice . iter_mut ( ) {
358
+ * slot = MaybeUninit :: new ( Default :: default ( ) ) ;
360
359
}
361
360
WriteChunk ( Some ( chunk) )
362
361
}
@@ -558,18 +557,33 @@ impl<T> WriteChunkUninit<'_, T> {
558
557
where
559
558
I : IntoIterator < Item = T > ,
560
559
{
561
- let iterated = self
562
- . first_slice
563
- . iter_mut ( )
564
- . chain ( self . second_slice . iter_mut ( ) )
565
- . zip ( iter)
566
- . map ( |( slot, item) | {
567
- // Safety: It is allowed to write to this memory slot
568
- unsafe {
569
- slot. as_mut_ptr ( ) . write ( item) ;
560
+ let mut iter = iter. into_iter ( ) ;
561
+ let mut iterated = 0 ;
562
+ // NB: Iterating over slices (instead of using pointers)
563
+ // led to worse optimization (with rustc 1.57).
564
+ ' outer: for & ( ptr, len) in & [
565
+ (
566
+ self . first_slice . as_mut_ptr ( ) . cast :: < T > ( ) ,
567
+ self . first_slice . len ( ) ,
568
+ ) ,
569
+ (
570
+ self . second_slice . as_mut_ptr ( ) . cast :: < T > ( ) ,
571
+ self . second_slice . len ( ) ,
572
+ ) ,
573
+ ] {
574
+ for i in 0 ..len {
575
+ match iter. next ( ) {
576
+ Some ( item) => {
577
+ // Safety: It is allowed to write to this memory slot
578
+ unsafe {
579
+ ptr. add ( i) . write ( item) ;
580
+ }
581
+ iterated += 1 ;
582
+ }
583
+ None => break ' outer,
570
584
}
571
- } )
572
- . count ( ) ;
585
+ }
586
+ }
573
587
// Safety: iterated slots have been initialized above
574
588
unsafe { self . commit_unchecked ( iterated) }
575
589
}
@@ -713,14 +727,13 @@ impl<T> ReadChunk<'_, T> {
713
727
}
714
728
715
729
unsafe fn commit_unchecked ( self , n : usize ) -> usize {
716
- for slot in self
717
- . first_slice
730
+ self . first_slice
718
731
. iter_mut ( )
719
732
. chain ( self . second_slice . iter_mut ( ) )
720
733
. take ( n)
721
- {
722
- slot. as_mut_ptr ( ) . drop_in_place ( ) ;
723
- }
734
+ . for_each ( |slot| {
735
+ slot. as_mut_ptr ( ) . drop_in_place ( ) ;
736
+ } ) ;
724
737
let c = self . consumer ;
725
738
let head = c. buffer ( ) . increment ( c. cached_head . get ( ) , n) ;
726
739
c. buffer ( ) . head . store ( head, Ordering :: Release ) ;
@@ -751,12 +764,8 @@ impl<'a, T> IntoIterator for ReadChunk<'a, T> {
751
764
/// Non-iterated items remain in the ring buffer.
752
765
fn into_iter ( self ) -> Self :: IntoIter {
753
766
Self :: IntoIter {
754
- chunk_size : self . len ( ) ,
755
- iter : self
756
- . first_slice
757
- . iter_mut ( )
758
- . chain ( self . second_slice . iter_mut ( ) ) ,
759
- consumer : self . consumer ,
767
+ chunk : self ,
768
+ iterated : 0 ,
760
769
}
761
770
}
762
771
}
@@ -770,22 +779,17 @@ impl<'a, T> IntoIterator for ReadChunk<'a, T> {
770
779
/// Non-iterated items remain in the ring buffer.
771
780
#[ derive( Debug ) ]
772
781
pub struct ReadChunkIntoIter < ' a , T > {
773
- chunk_size : usize ,
774
- iter : core:: iter:: Chain <
775
- core:: slice:: IterMut < ' a , MaybeUninit < T > > ,
776
- core:: slice:: IterMut < ' a , MaybeUninit < T > > ,
777
- > ,
778
- consumer : & ' a mut Consumer < T > ,
782
+ chunk : ReadChunk < ' a , T > ,
783
+ iterated : usize ,
779
784
}
780
785
781
786
impl < ' a , T > Drop for ReadChunkIntoIter < ' a , T > {
782
787
/// Makes all iterated slots available for writing again.
783
788
///
784
789
/// Non-iterated items remain in the ring buffer and are *not* dropped.
785
790
fn drop ( & mut self ) {
786
- let iterated = self . chunk_size - self . len ( ) ;
787
- let c = & self . consumer ;
788
- let head = c. buffer ( ) . increment ( c. cached_head . get ( ) , iterated) ;
791
+ let c = & self . chunk . consumer ;
792
+ let head = c. buffer ( ) . increment ( c. cached_head . get ( ) , self . iterated ) ;
789
793
c. buffer ( ) . head . store ( head, Ordering :: Release ) ;
790
794
c. cached_head . set ( head) ;
791
795
}
@@ -795,11 +799,24 @@ impl<'a, T> Iterator for ReadChunkIntoIter<'a, T> {
795
799
type Item = T ;
796
800
797
801
fn next ( & mut self ) -> Option < Self :: Item > {
798
- self . iter . next ( ) . map ( |slot| unsafe { slot. as_ptr ( ) . read ( ) } )
802
+ self . chunk
803
+ . first_slice
804
+ . get ( self . iterated )
805
+ . or_else ( || {
806
+ self . chunk
807
+ . second_slice
808
+ . get ( self . iterated - self . chunk . first_slice . len ( ) )
809
+ } )
810
+ . map ( |slot| unsafe { slot. as_ptr ( ) . read ( ) } )
811
+ . map ( |item| {
812
+ self . iterated += 1 ;
813
+ item
814
+ } )
799
815
}
800
816
801
817
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
802
- self . iter . size_hint ( )
818
+ let size = self . chunk . first_slice . len ( ) + self . chunk . second_slice . len ( ) - self . iterated ;
819
+ ( size, Some ( size) )
803
820
}
804
821
}
805
822
0 commit comments