diff --git a/src/db/db/dbEdgeProcessor.cc b/src/db/db/dbEdgeProcessor.cc index 4938b173a..8a1dca87e 100644 --- a/src/db/db/dbEdgeProcessor.cc +++ b/src/db/db/dbEdgeProcessor.cc @@ -1698,21 +1698,83 @@ private: int m_pn, m_ps; }; +const size_t skip_info_storage_threshold = 1; + class EdgeProcessorStates { public: struct SkipInfo { - SkipInfo (size_t _skip, size_t _skip_res) - : skip (_skip), skip_res (_skip_res) - { } + SkipInfo (size_t _skip, const std::vector &_skip_res) + : skip (_skip), m_skip_res_n (0), m_skip_res (0) + { + set_skip_res (_skip_res.begin (), _skip_res.end ()); + } SkipInfo () - : skip (0), skip_res (0) + : skip (0), m_skip_res_n (0), m_skip_res (0) { } + SkipInfo (const SkipInfo &si) + : skip (0), m_skip_res_n (0), m_skip_res (0) + { + operator= (si); + } + + ~SkipInfo () + { + if (m_skip_res_n > skip_info_storage_threshold) { + delete[] skip_res (); + } + } + + SkipInfo &operator= (const SkipInfo &si) + { + if (&si != this) { + skip = si.skip; + const size_t *n = si.skip_res (); + set_skip_res (n, n + si.m_skip_res_n); + } + return *this; + } + + template + void set_skip_res (Iter b, Iter e) + { + if (m_skip_res_n > skip_info_storage_threshold) { + delete[] (reinterpret_cast (m_skip_res)); + } + + m_skip_res_n = e - b; + if (m_skip_res_n <= skip_info_storage_threshold) { + if (b == e) { + m_skip_res = 0; + } else { + m_skip_res = *b; + } + } else { + size_t *t = new size_t[m_skip_res_n]; + m_skip_res = reinterpret_cast (t); + for (Iter i = b; i != e; ++i) { + *t++ = *i; + } + } + } + + const size_t *skip_res () const + { + if (m_skip_res_n <= skip_info_storage_threshold) { + return &m_skip_res; + } else { + return reinterpret_cast (m_skip_res); + } + } + size_t skip; - size_t skip_res; + + private: + size_t m_skip_res_n; + size_t m_skip_res; }; EdgeProcessorStates (const std::vector > &procs) @@ -1905,15 +1967,14 @@ public: * * This method will return true if at least one of the edge sinks received the edge */ - bool push_edge (const db::Edge &e) + void push_edge (const db::Edge &e) { - bool any = false; - for (std::vector::iterator s = m_states.begin (); s != m_states.end (); ++s) { + size_t i = 0; + for (std::vector::iterator s = m_states.begin (); s != m_states.end (); ++s, ++i) { if (s->push_edge (e)) { - any = true; + ++m_nres [i]; } } - return any; } /** @@ -1922,26 +1983,33 @@ public: * This is for optimization of the polygon generation. Stitching of edges does not happen if * there are no news. */ - void skip_n (size_t n) + void skip_n (const SkipInfo &si) { + const size_t *n = si.skip_res (); for (std::vector::iterator s = m_states.begin (); s != m_states.end (); ++s) { - s->skip_n (n); + s->skip_n (*n++); } } /** * @brief Gets a new SkipInfo entry */ - size_t skip_entry (size_t skip, size_t skip_res) + size_t skip_entry (size_t skip, const std::vector &skip_res) { if (! m_skip_queue.empty ()) { + size_t n = m_skip_queue.front (); m_skip_queue.pop_front (); - m_skip_info[n] = SkipInfo (skip, skip_res); + m_skip_info[n].skip = skip; + m_skip_info[n].set_skip_res (skip_res.begin (), skip_res.end ()); + return n + 1; + } else { + m_skip_info.push_back (SkipInfo (skip, skip_res)); return m_skip_info.size (); + } } @@ -1979,11 +2047,31 @@ public: } } + /** + * @brief Begins an interval that can potentially be skipped + */ + void begin_skip_interval () + { + m_nres.clear (); + m_nres.resize (m_states.size (), size_t (0)); + } + + /** + * @brief Finishes an interval that can potentially be skipped + * + * Returns the index of a new skip interval entry containing the skip information. + */ + size_t end_skip_interval (size_t skip) + { + return skip_entry (skip, m_nres); + } + private: std::vector m_states; bool m_selects_edges, m_prefer_touch; std::vector m_skip_info; std::list m_skip_queue; + std::vector m_nres; }; } @@ -2266,14 +2354,14 @@ EdgeProcessor::process (const std::vectordata); #ifdef DEBUG_EDGE_PROCESSOR - printf ("X %ld->%d,%d\n", long (c->data), int (skip_info.skip), int (skip_info.skip_res)); + printf ("X %ld->%d\n", long (c->data), int (skip_info.skip)); #endif if (skip_info.skip != 0 && (c + skip_info.skip >= future || (c + skip_info.skip)->data != 0)) { tl_assert (c + skip_info.skip <= future); - gs.skip_n (skip_info.skip_res); + gs.skip_n (skip_info); // skip this interval - has not changed c += skip_info.skip; @@ -2281,7 +2369,7 @@ EdgeProcessor::process (const std::vector::iterator c0 = c; - size_t n_res = 0; + gs.begin_skip_interval (); do { @@ -2388,9 +2476,7 @@ EdgeProcessor::process (const std::vectorend ()) { - if (gs.push_edge (*e)) { - ++n_res; - } + gs.push_edge (*e); } } @@ -2402,7 +2488,7 @@ EdgeProcessor::process (const std::vectordata = gs.skip_entry (std::distance (c0, c), n_res); + c0->data = gs.end_skip_interval (std::distance (c0, c)); }