@@ -42,7 +42,7 @@ public HexLayout()
4242
4343 public HexLayout ( List < T > hexes )
4444 {
45- existingHexes = new HexLayoutView ( hexes , true , false ) ;
45+ existingHexes = new HexLayoutView ( hexes , true , true ) ;
4646 }
4747
4848 /// <summary>
@@ -325,18 +325,16 @@ public bool Contains(T item)
325325 return existingHexes . Contains ( item ) ;
326326 }
327327
328- public void Approve ( bool isApproved = true )
328+ public void Approve ( )
329329 {
330- if ( isApproved )
331- {
332- existingHexes . Commit ( false ) ;
333- }
334- else
335- {
336- // This species will probably be discarded by auto-evo in this situation, so this returns the allocated
337- // memory to the pool.
338- existingHexes . Drop ( ) ;
339- }
330+ existingHexes . Commit ( false ) ;
331+ }
332+
333+ public void Reject ( )
334+ {
335+ // This species will probably be discarded by auto-evo in this situation, so this returns the allocated
336+ // memory to the pool.
337+ existingHexes . Drop ( ) ;
340338 }
341339
342340 // TODO: remove this bit of boxing here. https://nede.dev/blog/preventing-unnecessary-allocation-in-net-collections
@@ -488,12 +486,11 @@ protected struct HexLayoutView : IReadOnlyList<T>
488486 private const int MEMORY_ALLOC_SIZE = 16 ;
489487
490488 private T ? [ ] ? diffHexes ;
491- private int diffIndex ;
489+ private int diffIndex = 0 ;
492490
493491 public HexLayoutView ( List < T > parent , bool shared , bool initDiffHexes = false )
494492 {
495493 MainHexes = parent ;
496-
497494 Shared = shared ;
498495
499496 if ( initDiffHexes )
@@ -516,8 +513,7 @@ public T this[int index]
516513 {
517514 var item = diffHexes [ pendingIndex ] ;
518515
519- return item is null ? throw new ArgumentOutOfRangeException ( nameof ( index ) , "Out of range." ) :
520- diffHexes [ pendingIndex ] ! ;
516+ return item ?? throw new ArgumentOutOfRangeException ( nameof ( index ) , "Out of range." ) ;
521517 }
522518 }
523519
@@ -550,19 +546,15 @@ public void Add(T item)
550546 if ( diffHexes == null )
551547 {
552548 // No diff hexes, so we add directly to the layout.
553- if ( Shared )
554- {
555- // This is a shared hex layout. Since we're diverging from it, we need to allocate a brand-new list.
556549
557- MainHexes = [ ] ;
558- Shared = false ;
559- }
550+ // This is a shared hex layout. Since we're diverging from it, we need to allocate a brand-new list.
551+ IsolateIfShared ( ) ;
560552
561553 MainHexes . Add ( item ) ;
562554 return ;
563555 }
564556
565- if ( diffIndex == diffHexes . Length - 1 )
557+ if ( diffIndex == diffHexes . Length )
566558 {
567559 ArrayPool < T ? > . Shared . Resize ( ref diffHexes , diffHexes . Length + MEMORY_ALLOC_SIZE ) ;
568560 }
@@ -572,53 +564,40 @@ public void Add(T item)
572564
573565 public void Remove ( T item )
574566 {
575- if ( diffHexes = = null )
567+ if ( diffHexes ! = null )
576568 {
577- if ( Shared )
569+ for ( int i = 0 ; i < diffIndex ; ++ i )
578570 {
579- MainHexes = [ ] ;
580- Shared = false ;
581- }
571+ if ( ! ReferenceEquals ( item , diffHexes [ i ] ) )
572+ continue ;
582573
583- MainHexes . Remove ( item ) ;
584- return ;
574+ diffHexes [ i ] = diffHexes [ -- diffIndex ] ;
575+ diffHexes [ diffIndex ] = null ;
576+ return ;
577+ }
585578 }
586579
587- for ( int i = 0 ; i < diffIndex ; ++ i )
588- {
589- var toTest = diffHexes [ i ] ;
580+ IsolateIfShared ( ) ;
590581
591- if ( ! ReferenceEquals ( item , toTest ) )
592- continue ;
593-
594- diffHexes [ i ] = diffHexes [ -- diffIndex ] ;
595- diffHexes [ diffIndex ] = null ;
596-
597- break ;
598- }
582+ MainHexes . Remove ( item ) ;
599583 }
600584
601585 /// <summary>
602586 /// This method clears the diff layout and loads the modifications into the permanent layout.
603587 /// </summary>
604588 /// <remarks>
605- /// <para>
606- /// This is the method that allocates memory. Only when this is called and the diff is not empty the
607- /// organelles get deep cloned.
608- /// </para>
609- /// </remarks>>
610- /// <returns>true if this layout was in diff mode.</returns>>
589+ /// <para>
590+ /// This is the method that allocates memory. Only when this is called and the diff is not empty the
591+ /// organelles get deep cloned.
592+ /// </para>
593+ /// </remarks>
594+ /// <returns>true if this layout was in diff mode.</returns>
611595 public bool Commit ( bool reallocate )
612596 {
613597 if ( diffHexes is null || diffIndex == 0 )
614598 return false ;
615599
616- if ( Shared )
617- {
618- // Mark this not as shared now and allocate a new list.
619- MainHexes = new List < T > ( MainHexes ) ;
620- Shared = false ;
621- }
600+ IsolateIfShared ( ) ;
622601
623602 for ( int i = 0 ; i < diffIndex ; ++ i )
624603 {
@@ -644,12 +623,32 @@ public bool Commit(bool reallocate)
644623 return true ;
645624 }
646625
626+ public void IsolateIfShared ( )
627+ {
628+ if ( ! Shared )
629+ return ;
630+
631+ var count = MainHexes . Count ;
632+ var newList = new List < T > ( count ) ;
633+
634+ for ( int i = 0 ; i < count ; i ++ )
635+ {
636+ newList . Add ( ( T ) ( ( ICloneable ) MainHexes [ i ] ) . Clone ( ) ) ;
637+ }
638+
639+ MainHexes = newList ;
640+ Shared = false ;
641+ }
642+
647643 public void Drop ( )
648644 {
649645 if ( diffHexes is null )
650646 return ;
651647
652648 ArrayPool < T ? > . Shared . Return ( diffHexes , true ) ;
649+
650+ diffHexes = null ;
651+ diffIndex = 0 ;
653652 }
654653
655654 public IEnumerator < T > GetEnumerator ( )
@@ -662,7 +661,7 @@ public IEnumerator<T> GetEnumerator()
662661 if ( diffHexes == null )
663662 yield break ;
664663
665- for ( int i = 0 ; i < diffHexes . Length ; ++ i )
664+ for ( int i = 0 ; i < diffIndex ; ++ i )
666665 {
667666 var item = diffHexes [ i ] ;
668667
0 commit comments