@@ -548,6 +548,7 @@ class sharing_mapt
548
548
void add_item_if_not_shared (
549
549
const innert &container,
550
550
const innert &inner,
551
+ const std::size_t level,
551
552
delta_viewt &delta_view,
552
553
const bool only_common) const ;
553
554
@@ -564,6 +565,7 @@ class sharing_mapt
564
565
bool mark = true ) const ;
565
566
566
567
static const std::string not_found_msg;
568
+ static const std::size_t dummy_level;
567
569
568
570
// config
569
571
static const std::size_t bits;
@@ -792,67 +794,61 @@ ::gather_all(const innert &n, delta_viewt &delta_view) const
792
794
SHARING_MAPT (void )::add_item_if_not_shared(
793
795
const innert &container,
794
796
const innert &inner,
797
+ const std::size_t level,
795
798
delta_viewt &delta_view,
796
799
const bool only_common) const
797
800
{
798
- SM_ASSERT (!container.empty ());
799
- SM_ASSERT (!inner.empty ());
801
+ const leaft &l1 = container.get_container ().front ();
800
802
801
- std::stack< const innert *> stack ;
802
- stack. push (&inner );
803
+ const auto &k = l1. get_key () ;
804
+ std:: size_t key = hash ()(k );
803
805
804
- do
806
+ key >>= level * chunk;
807
+
808
+ const innert *ip = &inner;
809
+ SM_ASSERT (ip->is_defined_internal ());
810
+
811
+ while (true )
805
812
{
806
- const innert *ip = stack.top ();
807
- stack.pop ();
813
+ std::size_t bit = key & mask;
808
814
809
- SM_ASSERT (!ip-> empty () );
815
+ ip = ip-> find_child (bit );
810
816
811
- if (ip->is_internal ())
817
+ // only in first map
818
+ if (ip == nullptr )
812
819
{
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)
817
821
{
818
- const innert *i = &item.second ;
819
- stack.push (i);
822
+ delta_view.push_back ({k, l1.get_value ()});
820
823
}
821
- }
822
- else
823
- {
824
- SM_ASSERT (ip->is_container ());
825
824
826
- if (ip-> shares_with (container))
827
- return ;
825
+ return ;
826
+ }
828
827
829
- const leaft &l1 = container. get_container (). front ( );
828
+ SM_ASSERT (!ip-> empty () );
830
829
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 ;
833
835
834
- for (const auto &l : ll )
836
+ for (const auto &l2 : ip-> get_container () )
835
837
{
836
- if (l1.shares_with (l ))
838
+ if (l1.shares_with (l2 ))
837
839
return ;
838
840
839
- if (l1.get_key () == l .get_key ())
841
+ if (l1.get_key () == l2 .get_key ())
840
842
{
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 ()});
844
844
return ;
845
845
}
846
846
}
847
+
848
+ return ;
847
849
}
848
- }
849
- while (!stack.empty ());
850
850
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;
856
852
}
857
853
}
858
854
@@ -880,6 +876,8 @@ ::get_delta_view(
880
876
typedef std::pair<const innert *, const innert *> stack_itemt;
881
877
std::stack<stack_itemt> stack;
882
878
879
+ std::stack<std::size_t > level_stack;
880
+
883
881
// We do a DFS "in lockstep" simultaneously on both maps. For
884
882
// corresponding nodes we check whether they are shared between the
885
883
// maps, and if not, we recurse into the corresponding subtrees.
@@ -891,6 +889,7 @@ ::get_delta_view(
891
889
return ;
892
890
893
891
stack.push (stack_itemt (&map, &other.map ));
892
+ level_stack.push (0 );
894
893
895
894
do
896
895
{
@@ -901,6 +900,9 @@ ::get_delta_view(
901
900
902
901
stack.pop ();
903
902
903
+ const std::size_t level = level_stack.top ();
904
+ level_stack.pop ();
905
+
904
906
SM_ASSERT (!ip1->empty ());
905
907
SM_ASSERT (!ip2->empty ());
906
908
@@ -920,6 +922,11 @@ ::get_delta_view(
920
922
if (!child.shares_with (*ip2))
921
923
{
922
924
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);
923
930
}
924
931
}
925
932
@@ -947,6 +954,7 @@ ::get_delta_view(
947
954
else if (!child.shares_with (*p))
948
955
{
949
956
stack.push (stack_itemt (&child, p));
957
+ level_stack.push (level + 1 );
950
958
}
951
959
}
952
960
@@ -958,8 +966,9 @@ ::get_delta_view(
958
966
if (ip2->is_internal ())
959
967
{
960
968
SM_ASSERT (is_singular (ip1->get_container ()));
969
+ SM_ASSERT (level != dummy_level);
961
970
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);
963
972
964
973
continue ;
965
974
}
@@ -1283,6 +1292,7 @@ SHARING_MAPT2(optionalt<std::reference_wrapper<const, mapped_type>>)::find(
1283
1292
// static constants
1284
1293
1285
1294
SHARING_MAPT (const std::string)::not_found_msg="key not found";
1295
+ SHARING_MAPT (const std::size_t )::dummy_level = 0xff;
1286
1296
1287
1297
SHARING_MAPT (const std::size_t )::bits = 30;
1288
1298
SHARING_MAPT (const std::size_t )::chunk = 3;
0 commit comments