22#define OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP
33
44#include " contractor/query_edge.hpp"
5- #include " util/deallocating_vector.hpp"
65
6+ #include " util/integer_range.hpp"
7+ #include " util/permutation.hpp"
8+
9+ #include < tbb/parallel_sort.h>
10+
11+ #include < algorithm>
712#include < climits>
13+ #include < cstdint>
14+ #include < numeric>
15+ #include < vector>
816
917namespace osrm
1018{
@@ -43,7 +51,7 @@ struct ContractedEdgeContainer
4351 }
4452
4553 public:
46- void Insert (util::DeallocatingVector <QueryEdge> new_edges)
54+ void Insert (std::vector <QueryEdge> new_edges)
4755 {
4856 BOOST_ASSERT (edges.size () == 0 );
4957 BOOST_ASSERT (flags.empty ());
@@ -52,80 +60,68 @@ struct ContractedEdgeContainer
5260 flags.resize (edges.size (), ALL_FLAGS);
5361 }
5462
55- void Merge (util::DeallocatingVector <QueryEdge> new_edges)
63+ void Merge (std::vector <QueryEdge> new_edges)
5664 {
5765 BOOST_ASSERT (index < sizeof (MergedFlags) * CHAR_BIT);
5866
5967 const MergedFlags flag = 1 << index++;
6068
61- std::vector<MergedFlags> merged_flags;
62- merged_flags.reserve (flags.size () * 1.1 );
63- util::DeallocatingVector<QueryEdge> merged_edges;
64- merged_edges.reserve (edges.size () * 1.1 );
65-
69+ auto edge_iter = edges.cbegin ();
70+ auto edge_end = edges.cend ();
6671 auto flags_iter = flags.begin ();
67- // destructive iterators, this is single-pass only
68- // FIXME using dbegin() dend() will result in segfaults.
69- auto edges_iter = edges.dbegin ();
70- auto edges_end = edges.dend ();
71- auto new_edges_iter = new_edges.dbegin ();
72- auto new_edges_end = new_edges.dend ();
73-
74- while (edges_iter != edges_end && new_edges_iter != new_edges_end)
75- {
76- while (edges_iter != edges_end && mergeCompare (*edges_iter, *new_edges_iter))
77- {
78- merged_edges.push_back (*edges_iter);
79- merged_flags.push_back (*flags_iter);
80- edges_iter++;
81- flags_iter++;
82- }
8372
84- if (edges_iter == edges_end)
73+ // Remove all edges that are contained in the old set of edges and set the appropriate flag.
74+ auto new_end = std::remove_if (new_edges.begin (), new_edges.end (), [&](const auto &edge) {
75+ // check if the new edge would be sorted before the currend old edge
76+ // if so it is not contained yet in the set of old edges
77+ if (edge_iter == edge_end || mergeCompare (edge, *edge_iter))
8578 {
86- break ;
79+ return false ;
8780 }
8881
89- while (new_edges_iter != new_edges_end && mergeCompare (*new_edges_iter, *edges_iter))
82+ // find the first old edge that is equal or greater then the new edge
83+ while (edge_iter != edge_end && mergeCompare (*edge_iter, edge))
9084 {
91- merged_edges. push_back (*new_edges_iter );
92- merged_flags. push_back (flag) ;
93- new_edges_iter ++;
85+ BOOST_ASSERT (flags_iter != flags. end () );
86+ edge_iter++ ;
87+ flags_iter ++;
9488 }
9589
96- if (new_edges_iter == new_edges_end)
90+ // all new edges will be sorted after the old edges
91+ if (edge_iter == edge_end)
9792 {
98- break ;
93+ return false ;
9994 }
10095
101- while (edges_iter != edges_end && new_edges_iter != new_edges_end &&
102- mergable (*edges_iter , *new_edges_iter ))
96+ BOOST_ASSERT (edge_iter != edge_end);
97+ if ( mergable (edge , *edge_iter ))
10398 {
104- merged_edges.push_back (*edges_iter);
105- merged_flags.push_back (*flags_iter | flag);
106-
107- edges_iter++;
108- flags_iter++;
109- new_edges_iter++;
99+ *flags_iter = *flags_iter | flag;
100+ return true ;
110101 }
111- }
112-
113- while (edges_iter != edges_end)
114- {
115- BOOST_ASSERT (new_edges_iter == new_edges_end);
116- merged_edges.push_back (*edges_iter++);
117- merged_flags.push_back (*flags_iter++);
118- }
119-
120- while (new_edges_iter != new_edges_end)
121- {
122- BOOST_ASSERT (edges_iter == edges_end);
123- merged_edges.push_back (*new_edges_iter++);
124- merged_flags.push_back (flag);
125- }
126-
127- flags = std::move (merged_flags);
128- edges = std::move (merged_edges);
102+ BOOST_ASSERT (mergeCompare (edge, *edge_iter));
103+ return false ;
104+ });
105+
106+ // append new edges
107+ edges.insert (edges.end (), new_edges.begin (), new_end);
108+ auto edges_size = edges.size ();
109+ auto new_edges_size = std::distance (new_edges.begin (), new_end);
110+ BOOST_ASSERT (edges_size >= new_edges_size);
111+ flags.resize (edges_size);
112+ std::fill (flags.begin () + edges_size - new_edges_size, flags.end (), flag);
113+
114+ // enforce sorting for next merge step
115+ std::vector<unsigned > ordering (edges_size);
116+ std::iota (ordering.begin (), ordering.end (), 0 );
117+ tbb::parallel_sort (ordering.begin (), ordering.end (), [&](const auto lhs_idx, const auto rhs_idx) {
118+ return mergeCompare (edges[lhs_idx], edges[rhs_idx]);
119+ });
120+ auto permutation = util::orderingToPermutation (ordering);
121+
122+ util::inplacePermutation (edges.begin (), edges.end (), permutation);
123+ util::inplacePermutation (flags.begin (), flags.end (), permutation);
124+ BOOST_ASSERT (std::is_sorted (edges.begin (), edges.end (), mergeCompare));
129125 }
130126
131127 auto MakeEdgeFilters () const
@@ -145,7 +141,7 @@ struct ContractedEdgeContainer
145141
146142 std::size_t index = 0 ;
147143 std::vector<MergedFlags> flags;
148- util::DeallocatingVector <QueryEdge> edges;
144+ std::vector <QueryEdge> edges;
149145};
150146}
151147}
0 commit comments