@@ -453,7 +453,7 @@ class sharing_mapt
453
453
if (empty ())
454
454
return ;
455
455
456
- iterate(map, 0 , f);
456
+ iterate(map, f);
457
457
}
458
458
459
459
#if !defined(_MSC_VER)
@@ -525,12 +525,15 @@ class sharing_mapt
525
525
}
526
526
527
527
void iterate(
528
- const baset &n,
529
- const unsigned start_depth,
528
+ const innert &n,
530
529
std::function<void (const key_type &k, const mapped_type &m)> f) const ;
531
530
532
- void gather_all (const baset &n, const unsigned depth, delta_viewt &delta_view)
533
- const ;
531
+ void gather_all (const innert &n, delta_viewt &delta_view) const ;
532
+
533
+ bool is_singular (const leaf_listt &ll) const
534
+ {
535
+ return !ll.empty () && std::next (ll.begin ()) == ll.end ();
536
+ }
534
537
535
538
std::size_t count_unmarked_nodes (
536
539
bool leafs_only,
@@ -559,42 +562,37 @@ class sharing_mapt
559
562
560
563
SHARING_MAPT (void )
561
564
::iterate(
562
- const baset &n,
563
- unsigned start_depth,
565
+ const innert &n,
564
566
std::function<void (const key_type &k, const mapped_type &m)> f) const
565
567
{
566
- typedef std::pair< unsigned , const baset *> stack_itemt ;
568
+ SM_ASSERT (!n. empty ()) ;
567
569
568
- std::stack<stack_itemt > stack;
569
- stack.push ({start_depth, &n} );
570
+ std::stack<const innert * > stack;
571
+ stack.push (&n );
570
572
571
573
do
572
574
{
573
- const stack_itemt &si = stack.top ();
574
-
575
- const unsigned depth = si.first ;
576
- const baset *bp = si.second ;
577
-
575
+ const innert *ip = stack.top ();
578
576
stack.pop ();
579
577
580
- if (depth < steps) // internal
578
+ SM_ASSERT (!ip->empty ());
579
+
580
+ if (ip->is_internal ())
581
581
{
582
- const innert *ip = static_cast <const innert *>(bp);
583
582
const to_mapt &m = ip->get_to_map ();
584
583
SM_ASSERT (!m.empty ());
585
584
586
585
for (const auto &item : m)
587
586
{
588
587
const innert *i = &item.second ;
589
- stack.push ({depth + 1 , i} );
588
+ stack.push (i );
590
589
}
591
590
}
592
- else // container
591
+ else
593
592
{
594
- SM_ASSERT (depth == steps );
593
+ SM_ASSERT (ip-> is_container () );
595
594
596
- const innert *cp = static_cast <const innert *>(bp);
597
- const leaf_listt &ll = cp->get_container ();
595
+ const leaf_listt &ll = ip->get_container ();
598
596
SM_ASSERT (!ll.empty ());
599
597
600
598
for (const auto &l : ll)
@@ -617,23 +615,15 @@ ::count_unmarked_nodes(
617
615
618
616
unsigned count = 0 ;
619
617
620
- // depth, node pointer
621
- typedef std::pair<unsigned , const baset *> stack_itemt;
622
-
623
- std::stack<stack_itemt> stack;
624
- stack.push ({0 , &map});
618
+ std::stack<const innert *> stack;
619
+ stack.push (&map);
625
620
626
621
do
627
622
{
628
- const stack_itemt &si = stack.top ();
629
-
630
- const unsigned depth = si.first ;
631
- const baset *bp = si.second ;
632
-
623
+ const innert *ip = stack.top ();
633
624
stack.pop ();
634
625
635
626
// internal node or container node
636
- const innert *ip = static_cast <const innert *>(bp);
637
627
const unsigned use_count = ip->use_count ();
638
628
const void *raw_ptr = ip->is_internal ()
639
629
? (const void *)&ip->read_internal ()
@@ -657,20 +647,22 @@ ::count_unmarked_nodes(
657
647
count++;
658
648
}
659
649
660
- if (depth < steps) // internal
650
+ if (ip-> is_internal ())
661
651
{
652
+ SM_ASSERT (!ip->empty ());
653
+
662
654
const to_mapt &m = ip->get_to_map ();
663
655
SM_ASSERT (!m.empty ());
664
656
665
657
for (const auto &item : m)
666
658
{
667
659
const innert *i = &item.second ;
668
- stack.push ({depth + 1 , i} );
660
+ stack.push (i );
669
661
}
670
662
}
671
- else // container
663
+ else
672
664
{
673
- SM_ASSERT (depth == steps );
665
+ SM_ASSERT (ip-> is_defined_container () );
674
666
675
667
const leaf_listt &ll = ip->get_container ();
676
668
SM_ASSERT (!ll.empty ());
@@ -766,17 +758,17 @@ SHARING_MAPT(void)::get_view(viewt &view) const
766
758
view.push_back (view_itemt (k, m));
767
759
};
768
760
769
- iterate(map, 0 , f);
761
+ iterate(map, f);
770
762
}
771
763
772
764
SHARING_MAPT (void )
773
- ::gather_all(const baset &n, unsigned depth , delta_viewt &delta_view) const
765
+ ::gather_all(const innert &n, delta_viewt &delta_view) const
774
766
{
775
767
auto f = [&delta_view](const key_type &k, const mapped_type &m) {
776
768
delta_view.push_back (delta_view_itemt (false , k, m, dummy));
777
769
};
778
770
779
- iterate(n, depth, f);
771
+ iterate(n, f);
780
772
}
781
773
782
774
SHARING_MAPT (void )
@@ -794,13 +786,13 @@ ::get_delta_view(
794
786
{
795
787
if (!only_common)
796
788
{
797
- gather_all (map, 0 , delta_view);
789
+ gather_all (map, delta_view);
798
790
}
799
791
800
792
return ;
801
793
}
802
794
803
- typedef std::tuple< unsigned , const baset *, const baset *> stack_itemt;
795
+ typedef std::pair< const innert *, const innert *> stack_itemt;
804
796
std::stack<stack_itemt> stack;
805
797
806
798
// We do a DFS "in lockstep" simultaneously on both maps. For
@@ -810,71 +802,106 @@ ::get_delta_view(
810
802
// The stack contains the children of already visited nodes that we
811
803
// still have to visit during the traversal.
812
804
813
- stack.push (stack_itemt (0 , &map, &other.map ));
805
+ if (map.shares_with (other.map ))
806
+ return ;
807
+
808
+ stack.push (stack_itemt (&map, &other.map ));
814
809
815
810
do
816
811
{
817
812
const stack_itemt &si = stack.top ();
818
813
819
- const unsigned depth = std::get<0 >(si);
820
- const baset *bp1 = std::get<1 >(si);
821
- const baset *bp2 = std::get<2 >(si);
814
+ const innert *ip1 = si.first ;
815
+ const innert *ip2 = si.second ;
822
816
823
817
stack.pop ();
824
818
825
- if (depth < steps) // internal
819
+ SM_ASSERT (!ip1->empty ());
820
+ SM_ASSERT (!ip2->empty ());
821
+
822
+ if (ip1->is_internal () && ip2->is_container ())
826
823
{
827
- const innert *ip1 = static_cast <const innert *>(bp1);
828
- const innert *ip2 = static_cast <const innert *>(bp2);
824
+ // The container *ip2 contains one element as only containers at the
825
+ // bottom of the tree can have more than one element. This happens when
826
+ // two different keys have the same hash code. It is known here that *ip2
827
+ // is not at the bottom of the tree, as *ip1 (the corresponding node in
828
+ // the other map) is an internal node, and internal nodes cannot be at the
829
+ // bottom of the map.
830
+ SM_ASSERT (is_singular (ip2->get_container ()));
831
+
832
+ for (const auto &item : ip1->get_to_map ())
833
+ {
834
+ const innert &child = item.second ;
835
+ SM_ASSERT (!child.shares_with (*ip2));
836
+ stack.push (stack_itemt (&child, ip2));
837
+ }
829
838
830
- const to_mapt &m = ip1->get_to_map ();
839
+ continue ;
840
+ }
831
841
832
- for (const auto &item : m)
842
+ if (ip1->is_internal ())
843
+ {
844
+ SM_ASSERT (ip2->is_internal ());
845
+
846
+ for (const auto &item : ip1->get_to_map ())
833
847
{
834
- const innert *p ;
848
+ const innert &child = item. second ;
835
849
850
+ const innert *p;
836
851
p = ip2->find_child (item.first );
837
- if (p==nullptr )
852
+
853
+ if (p == nullptr )
838
854
{
839
855
if (!only_common)
840
856
{
841
- gather_all (item. second , depth + 1 , delta_view);
857
+ gather_all (child , delta_view);
842
858
}
843
859
}
844
- else if (!item. second .shares_with (*p))
860
+ else if (!child .shares_with (*p))
845
861
{
846
- stack.push (stack_itemt (depth + 1 , &item. second , p));
862
+ stack.push (stack_itemt (&child , p));
847
863
}
848
864
}
865
+
866
+ continue ;
849
867
}
850
- else // container
851
- {
852
- SM_ASSERT (depth == steps);
853
868
854
- const innert *cp1 = static_cast <const innert *>(bp1);
855
- const innert *cp2 = static_cast <const innert *>(bp2);
869
+ SM_ASSERT (ip1->is_container ());
856
870
857
- const leaf_listt &ll1 = cp1->get_container ();
871
+ if (ip2->is_internal ())
872
+ {
873
+ SM_ASSERT (is_singular (ip1->get_container ()));
858
874
859
- for (const auto &l1 : ll1 )
875
+ for (const auto &item : ip2-> get_to_map () )
860
876
{
861
- const key_type &k1=l1.get_key ();
862
- const leaft *p;
877
+ const innert &child = item.second ;
878
+ SM_ASSERT (!ip1->shares_with (child));
879
+ stack.push (stack_itemt (ip1, &child));
880
+ }
863
881
864
- p = cp2->find_leaf (k1);
882
+ continue ;
883
+ }
865
884
866
- if (p != nullptr )
867
- {
868
- if (!l1.shares_with (*p))
869
- {
870
- delta_view.push_back ({true , k1, l1.get_value (), p->get_value ()});
871
- }
872
- }
873
- else if (!only_common)
885
+ SM_ASSERT (ip2->is_container ());
886
+
887
+ for (const auto &l1 : ip1->get_container ())
888
+ {
889
+ const key_type &k1 = l1.get_key ();
890
+ const leaft *p;
891
+
892
+ p = ip2->find_leaf (k1);
893
+
894
+ if (p != nullptr )
895
+ {
896
+ if (!l1.shares_with (*p))
874
897
{
875
- delta_view.push_back ({false , l1. get_key () , l1.get_value (), dummy });
898
+ delta_view.push_back ({true , k1 , l1.get_value (), p-> get_value () });
876
899
}
877
900
}
901
+ else if (!only_common)
902
+ {
903
+ delta_view.push_back ({false , l1.get_key (), l1.get_value (), dummy});
904
+ }
878
905
}
879
906
}
880
907
while (!stack.empty ());
@@ -894,6 +921,8 @@ SHARING_MAPT2(, innert *)::get_container_node(const key_type &k)
894
921
key >>= chunk;
895
922
}
896
923
924
+ SM_ASSERT (ip->is_container ());
925
+
897
926
return ip;
898
927
}
899
928
@@ -916,6 +945,8 @@ SHARING_MAPT2(const, innert *)::get_container_node(const key_type &k) const
916
945
key >>= chunk;
917
946
}
918
947
948
+ SM_ASSERT (ip->is_defined_container ());
949
+
919
950
return ip;
920
951
}
921
952
0 commit comments