@@ -548,6 +548,7 @@ class sharing_mapt
548548 void add_item_if_not_shared (
549549 const innert &container,
550550 const innert &inner,
551+ const std::size_t level,
551552 delta_viewt &delta_view,
552553 const bool only_common) const ;
553554
@@ -564,6 +565,7 @@ class sharing_mapt
564565 bool mark = true ) const ;
565566
566567 static const std::string not_found_msg;
568+ static const std::size_t dummy_level;
567569
568570 // config
569571 static const std::size_t bits;
@@ -792,67 +794,61 @@ ::gather_all(const innert &n, delta_viewt &delta_view) const
792794SHARING_MAPT (void )::add_item_if_not_shared(
793795 const innert &container,
794796 const innert &inner,
797+ const std::size_t level,
795798 delta_viewt &delta_view,
796799 const bool only_common) const
797800{
798- SM_ASSERT (!container.empty ());
799- SM_ASSERT (!inner.empty ());
801+ const leaft &l1 = container.get_container ().front ();
800802
801- std::stack< const innert *> stack ;
802- stack. push (&inner );
803+ const auto &k = l1. get_key () ;
804+ std:: size_t key = hash ()(k );
803805
804- do
806+ key >>= level * chunk;
807+
808+ const innert *ip = &inner;
809+ SM_ASSERT (ip->is_defined_internal ());
810+
811+ while (true )
805812 {
806- const innert *ip = stack.top ();
807- stack.pop ();
813+ std::size_t bit = key & mask;
808814
809- SM_ASSERT (!ip-> empty () );
815+ ip = ip-> find_child (bit );
810816
811- if (ip->is_internal ())
817+ // only in first map
818+ if (ip == nullptr )
812819 {
813- const to_mapt &m = ip->get_to_map ();
814- SM_ASSERT (!m.empty ());
815-
816- for (const auto &item : m)
820+ if (!only_common)
817821 {
818- const innert *i = &item.second ;
819- stack.push (i);
822+ delta_view.push_back ({k, l1.get_value ()});
820823 }
821- }
822- else
823- {
824- SM_ASSERT (ip->is_container ());
825824
826- if (ip-> shares_with (container))
827- return ;
825+ return ;
826+ }
828827
829- const leaft &l1 = container. get_container (). front ( );
828+ SM_ASSERT (!ip-> empty () );
830829
831- const leaf_listt &ll = ip->get_container ();
832- SM_ASSERT (!ll.empty ());
830+ // potentially in both maps
831+ if (ip->is_container ())
832+ {
833+ if (container.shares_with (*ip))
834+ return ;
833835
834- for (const auto &l : ll )
836+ for (const auto &l2 : ip-> get_container () )
835837 {
836- if (l1.shares_with (l ))
838+ if (l1.shares_with (l2 ))
837839 return ;
838840
839- if (l1.get_key () == l .get_key ())
841+ if (l1.get_key () == l2 .get_key ())
840842 {
841- // element is in both maps and not shared
842- delta_view.push_back (
843- {true , l1.get_key (), l1.get_value (), l.get_value ()});
843+ delta_view.push_back ({k, l1.get_value (), l2.get_value ()});
844844 return ;
845845 }
846846 }
847+
848+ return ;
847849 }
848- }
849- while (!stack.empty ());
850850
851- // element is only in first map
852- if (!only_common)
853- {
854- const leaft &l1 = container.get_container ().front ();
855- delta_view.push_back ({false , l1.get_key (), l1.get_value (), dummy});
851+ key >>= chunk;
856852 }
857853}
858854
@@ -880,6 +876,8 @@ ::get_delta_view(
880876 typedef std::pair<const innert *, const innert *> stack_itemt;
881877 std::stack<stack_itemt> stack;
882878
879+ std::stack<std::size_t > level_stack;
880+
883881 // We do a DFS "in lockstep" simultaneously on both maps. For
884882 // corresponding nodes we check whether they are shared between the
885883 // maps, and if not, we recurse into the corresponding subtrees.
@@ -891,6 +889,7 @@ ::get_delta_view(
891889 return ;
892890
893891 stack.push (stack_itemt (&map, &other.map ));
892+ level_stack.push (0 );
894893
895894 do
896895 {
@@ -901,6 +900,9 @@ ::get_delta_view(
901900
902901 stack.pop ();
903902
903+ const std::size_t level = level_stack.top ();
904+ level_stack.pop ();
905+
904906 SM_ASSERT (!ip1->empty ());
905907 SM_ASSERT (!ip2->empty ());
906908
@@ -920,6 +922,11 @@ ::get_delta_view(
920922 if (!child.shares_with (*ip2))
921923 {
922924 stack.push (stack_itemt (&child, ip2));
925+
926+ // The level is not needed when the node of the left map is an
927+ // internal node, and the node of the right map is a container node,
928+ // hence we just push a dummy element
929+ level_stack.push (dummy_level);
923930 }
924931 }
925932
@@ -947,6 +954,7 @@ ::get_delta_view(
947954 else if (!child.shares_with (*p))
948955 {
949956 stack.push (stack_itemt (&child, p));
957+ level_stack.push (level + 1 );
950958 }
951959 }
952960
@@ -958,8 +966,9 @@ ::get_delta_view(
958966 if (ip2->is_internal ())
959967 {
960968 SM_ASSERT (is_singular (ip1->get_container ()));
969+ SM_ASSERT (level != dummy_level);
961970
962- add_item_if_not_shared (*ip1, *ip2, delta_view, only_common);
971+ add_item_if_not_shared (*ip1, *ip2, level, delta_view, only_common);
963972
964973 continue ;
965974 }
@@ -1283,6 +1292,7 @@ SHARING_MAPT2(optionalt<std::reference_wrapper<const, mapped_type>>)::find(
12831292// static constants
12841293
12851294SHARING_MAPT (const std::string)::not_found_msg=" key not found" ;
1295+ SHARING_MAPT (const std::size_t )::dummy_level = 0xff ;
12861296
12871297SHARING_MAPT (const std::size_t )::bits = 30 ;
12881298SHARING_MAPT (const std::size_t )::chunk = 3 ;
0 commit comments