From 37d8f0bfca80c9a923aa454269eeb63e858baa5d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 31 Dec 2018 16:41:32 +0100 Subject: [PATCH] Added hierarchical progress reporting for more detailed progress. --- src/db/db/dbHierNetworkProcessor.cc | 17 ++- src/lay/lay/layMainWindow.cc | 59 ++------ src/lay/lay/layMainWindow.h | 16 +-- src/lay/lay/layProgress.cc | 46 +++---- src/lay/lay/layProgress.h | 6 +- src/lay/lay/layTextProgress.cc | 16 +-- src/lay/lay/layTextProgress.h | 4 +- src/tl/tl/tlList.h | 30 ++-- src/tl/tl/tlProgress.cc | 33 ++++- src/tl/tl/tlProgress.h | 23 ++++ src/tl/unit_tests/tlListTests.cc | 206 ++++++++++++++++------------ 11 files changed, 241 insertions(+), 215 deletions(-) diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index eadc2b973..7f6cc1289 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -535,7 +535,10 @@ template void local_clusters::build_clusters (const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn) { - db::box_scanner > bs; + bool report_progress = tl::verbosity () >= 50; + static std::string desc = tl::to_string (tr ("Building local clusters")); + + db::box_scanner > bs (report_progress, desc); typename T::tag object_tag; db::box_convert bc; @@ -1306,9 +1309,11 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c // handle instance to instance connections { - tl::SelfTimer timer (tl::verbosity () >= 51, tl::to_string (tr ("Instance to instance treatment"))); + static std::string desc = tl::to_string (tr ("Instance to instance treatment")); + tl::SelfTimer timer (tl::verbosity () >= 51, desc); - db::box_scanner bs; + bool report_progress = tl::verbosity () >= 50; + db::box_scanner bs (report_progress, desc); for (std::vector::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) { bs.insert (inst.operator-> (), 0); @@ -1320,9 +1325,11 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c // handle local to instance connections { - tl::SelfTimer timer (tl::verbosity () >= 51, tl::to_string (tr ("Local to instance treatment"))); + static std::string desc = tl::to_string (tr ("Local to instance treatment")); + tl::SelfTimer timer (tl::verbosity () >= 51, desc); - db::box_scanner2, unsigned int, db::Instance, unsigned int> bs2; + bool report_progress = tl::verbosity () >= 50; + db::box_scanner2, unsigned int, db::Instance, unsigned int> bs2 (report_progress, desc); for (typename connected_clusters::const_iterator c = local.begin (); c != local.end (); ++c) { bs2.insert1 (c.operator-> (), 0); diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index d988c1a33..352f6e504 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -379,24 +379,10 @@ TextProgressDelegate::TextProgressDelegate (MainWindow *mw, int verbosity) // .. nothing yet .. } -void TextProgressDelegate::set_progress_can_cancel (bool f) +void TextProgressDelegate::update_progress (tl::Progress *progress) { - if (!mp_mw->set_progress_can_cancel (f)) { - lay::TextProgress::set_progress_can_cancel (f); - } -} - -void TextProgressDelegate::set_progress_text (const std::string &text) -{ - if (!mp_mw->set_progress_text (text)) { - lay::TextProgress::set_progress_text (text); - } -} - -void TextProgressDelegate::set_progress_value (double v, const std::string &value) -{ - if (!mp_mw->set_progress_value (v, value)) { - lay::TextProgress::set_progress_value (v, value); + if (!mp_mw->update_progress (progress)) { + lay::TextProgress::update_progress (progress); } } @@ -4642,42 +4628,27 @@ MainWindow::progress_get_widget () const } bool -MainWindow::set_progress_can_cancel (bool f) +MainWindow::update_progress (tl::Progress *progress) { - if (mp_progress_dialog) { - mp_progress_dialog->set_can_cancel (f); - return true; - } else if (isVisible () && mp_progress_widget) { - mp_progress_widget->set_can_cancel (f); - return true; - } else { - return false; - } -} + bool can_cancel = progress->can_cancel (); + std::string text = progress->desc (); + std::string value = progress->formatted_value (); + double v = progress->value (); -bool -MainWindow::set_progress_text (const std::string &text) -{ if (mp_progress_dialog) { + + mp_progress_dialog->set_can_cancel (can_cancel); mp_progress_dialog->set_text (text); - return true; - } else if (isVisible () && mp_progress_widget) { - mp_progress_widget->set_text (text); - return true; - } else { - return false; - } -} - -bool -MainWindow::set_progress_value (double v, const std::string &value) -{ - if (mp_progress_dialog) { mp_progress_dialog->set_value (v, value); return true; + } else if (isVisible () && mp_progress_widget) { + + mp_progress_widget->set_can_cancel (can_cancel); + mp_progress_widget->set_text (text); mp_progress_widget->set_value (v, value); return true; + } else { return false; } diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index cc3b21bf4..8bb84bd04 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -105,9 +105,7 @@ class TextProgressDelegate public: TextProgressDelegate (MainWindow *mw, int verbosity); - virtual void set_progress_can_cancel (bool f); - virtual void set_progress_text (const std::string &text); - virtual void set_progress_value (double v, const std::string &value); + virtual void update_progress (tl::Progress *progress); virtual void show_progress_bar (bool show); virtual bool progress_wants_widget () const; virtual void progress_add_widget (QWidget *widget); @@ -381,17 +379,7 @@ public: /** * @brief Implementation of the lay::ProgressBar interface: set the flag indicating whether we can cancel the operation */ - bool set_progress_can_cancel(bool f); - - /** - * @brief Implementation of the lay::ProgressBar interface: set the text to display - */ - bool set_progress_text (const std::string &text); - - /** - * @brief Implementation of the lay::ProgressBar interface: set the value to display - */ - bool set_progress_value (double v, const std::string &value); + bool update_progress (tl::Progress *progress); /** * @brief Implementation of the lay::ProgressBar interface: Returns a value indicating whether a progress widget is wanted diff --git a/src/lay/lay/layProgress.cc b/src/lay/lay/layProgress.cc index daefbaff1..1a0af1d0a 100644 --- a/src/lay/lay/layProgress.cc +++ b/src/lay/lay/layProgress.cc @@ -92,7 +92,7 @@ ProgressReporter::register_object (tl::Progress *progress) QApplication::instance ()->installEventFilter (this); } - mp_objects.push_back (progress); // this keeps the outmost one visible. push_front would make the latest one visible. + mp_objects.push_back (*progress); // this keeps the outmost one visible. push_front would make the latest one visible. // mp_objects.push_front (progress); if (m_start_time == tl::Clock () && ! m_pw_visible) { @@ -110,36 +110,27 @@ ProgressReporter::register_object (tl::Progress *progress) void ProgressReporter::unregister_object (tl::Progress *progress) { - for (std::list ::iterator k = mp_objects.begin (); k != mp_objects.end (); ++k) { - - if (*k == progress) { - - mp_objects.erase (k); - - // close or refresh window - if (mp_objects.empty ()) { - if (m_pw_visible) { - set_visible (false); - } - m_start_time = tl::Clock (); - } - - update_and_yield (); - break; + progress->unlink (); + // close or refresh window + if (mp_objects.empty ()) { + if (m_pw_visible) { + set_visible (false); } - + m_start_time = tl::Clock (); } + update_and_yield (); + if (mp_objects.empty ()) { QApplication::instance ()->removeEventFilter (this); } } void -ProgressReporter::trigger (tl::Progress *progress) +ProgressReporter::trigger (tl::Progress * /*progress*/) { - if (! mp_objects.empty () && mp_objects.front () == progress) { + if (! mp_objects.empty ()) { // make dialog visible after some time has passed if (! m_pw_visible && (tl::Clock::current () - m_start_time).seconds () > 1.0) { set_visible (true); @@ -164,8 +155,8 @@ ProgressReporter::yield (tl::Progress * /*progress*/) void ProgressReporter::signal_break () { - for (std::list ::iterator k = mp_objects.begin (); k != mp_objects.end (); ++k) { - (*k)->signal_break (); + for (tl::list::iterator k = mp_objects.begin (); k != mp_objects.end (); ++k) { + k->signal_break (); } } @@ -174,13 +165,10 @@ ProgressReporter::update_and_yield () { if (m_pw_visible && ! mp_objects.empty ()) { if (mp_pb) { - // not supported yet: mp_pb->progress_widget ()->set_title ((*mp_objects.begin ())->title ()); - mp_pb->set_progress_can_cancel (mp_objects.front ()->can_cancel ()); - mp_pb->set_progress_text (mp_objects.front ()->desc ()); - mp_pb->set_progress_value (mp_objects.front ()->value (), mp_objects.front ()->formatted_value ()); + mp_pb->update_progress (mp_objects.first ()); QWidget *w = mp_pb->progress_get_widget (); if (w) { - mp_objects.front ()->render_progress (w); + mp_objects.first ()->render_progress (w); } } process_events (); // Qt4 seems to need this @@ -214,8 +202,8 @@ ProgressReporter::set_visible (bool vis) if (mp_pb) { if (!vis) { mp_pb->progress_remove_widget (); - } else if (mp_pb->progress_wants_widget () && mp_objects.front ()) { - mp_pb->progress_add_widget (mp_objects.front ()->progress_widget ()); + } else if (mp_pb->progress_wants_widget () && mp_objects.first ()) { + mp_pb->progress_add_widget (mp_objects.first ()->progress_widget ()); } } diff --git a/src/lay/lay/layProgress.h b/src/lay/lay/layProgress.h index dcaa5e405..a84549535 100644 --- a/src/lay/lay/layProgress.h +++ b/src/lay/lay/layProgress.h @@ -47,9 +47,7 @@ class LAY_PUBLIC ProgressBar public: virtual ~ProgressBar () { } - virtual void set_progress_can_cancel (bool f) = 0; - virtual void set_progress_text (const std::string &text) = 0; - virtual void set_progress_value (double v, const std::string &value) = 0; + virtual void update_progress (tl::Progress *progress) = 0; virtual bool progress_wants_widget () const { return false; } virtual void progress_add_widget (QWidget * /*widget*/) { } virtual void progress_remove_widget () { } @@ -79,7 +77,7 @@ public: } private: - std::list mp_objects; + tl::list mp_objects; tl::Clock m_start_time; lay::ProgressBar *mp_pb; bool m_pw_visible; diff --git a/src/lay/lay/layTextProgress.cc b/src/lay/lay/layTextProgress.cc index 604509dae..a466b933c 100644 --- a/src/lay/lay/layTextProgress.cc +++ b/src/lay/lay/layTextProgress.cc @@ -33,21 +33,19 @@ TextProgress::TextProgress (int verbosity) // .. nothing yet .. } -void TextProgress::set_progress_can_cancel (bool /*f*/) -{ - // .. nothing yet .. -} - -void TextProgress::set_progress_text (const std::string &text) +void TextProgress::update_progress (tl::Progress *progress) { + std::string text = progress->desc (); if (m_progress_text != text && tl::verbosity () >= m_verbosity) { tl::info << text << " .."; m_progress_text = text; } -} -void TextProgress::set_progress_value (double /*value*/, const std::string &value) -{ + std::string value = progress->formatted_value (); + for (tl::Progress *p = progress->next (); p != 0; p = p->next ()) { + value += " " + p->formatted_value (); + } + if (m_progress_value != value && tl::verbosity () >= m_verbosity) { tl::info << ".. " << value; m_progress_value = value; diff --git a/src/lay/lay/layTextProgress.h b/src/lay/lay/layTextProgress.h index fef73db26..23a0638b7 100644 --- a/src/lay/lay/layTextProgress.h +++ b/src/lay/lay/layTextProgress.h @@ -46,9 +46,7 @@ public: */ TextProgress (int verbosity); - virtual void set_progress_can_cancel (bool f); - virtual void set_progress_text (const std::string &text); - virtual void set_progress_value (double v, const std::string &value); + virtual void update_progress (tl::Progress *progress); virtual void show_progress_bar (bool show); private: diff --git a/src/tl/tl/tlList.h b/src/tl/tl/tlList.h index 226b89ff7..ff66cb359 100644 --- a/src/tl/tl/tlList.h +++ b/src/tl/tl/tlList.h @@ -94,6 +94,7 @@ public: tl_assert (mp_next->mp_prev == this); mp_next->mp_prev = mp_prev; } + mp_prev = mp_next = 0; } private: @@ -127,11 +128,16 @@ public: void clear () { while (! empty ()) { - if (first ()->m_owned) { - delete first (); - } else { - first ()->unlink (); - } + erase (first ()); + } + } + + void erase (C *c) + { + if (c->m_owned) { + delete c; + } else { + c->unlink (); } } @@ -192,22 +198,22 @@ public: void insert (C *after, C &new_obj) { - insert_impl (after, new_obj, false); + insert_impl (after, &new_obj, false); } void insert_before (C *before, C &new_obj) { - insert_before_impl (before, new_obj, false); + insert_before_impl (before, &new_obj, false); } void push_back (C &new_obj) { - push_back_impl (new_obj, false); + push_back_impl (&new_obj, false); } void push_front (C &new_obj) { - push_front_impl (new_obj, false); + push_front_impl (&new_obj, false); } size_t size () const @@ -248,10 +254,9 @@ private: list_node *after_node = after; if (! after) { after_node = &m_head; - } else { - after_node->m_owned = owned; } + new_obj->m_owned = owned; new_obj->mp_next = after_node->mp_next; after_node->mp_next = new_obj; new_obj->mp_prev = after_node; @@ -263,10 +268,9 @@ private: list_node *before_node = before; if (! before) { before_node = &m_back; - } else { - before_node->m_owned = owned; } + new_obj->m_owned = owned; new_obj->mp_prev = before_node->mp_prev; before_node->mp_prev = new_obj; new_obj->mp_next = before_node; diff --git a/src/tl/tl/tlProgress.cc b/src/tl/tl/tlProgress.cc index a1501caa9..84df5ea01 100644 --- a/src/tl/tl/tlProgress.cc +++ b/src/tl/tl/tlProgress.cc @@ -72,6 +72,17 @@ Progress::Progress (const std::string &desc, size_t yield_interval) m_last_value (-1.0), m_can_cancel (true), m_cancelled (false) +{ + // .. nothing yet .. +} + +Progress::~Progress () +{ + // .. nothing yet .. +} + +void +Progress::initialize () { ProgressAdaptor *a = adaptor (); if (a) { @@ -79,7 +90,8 @@ Progress::Progress (const std::string &desc, size_t yield_interval) } } -Progress::~Progress () +void +Progress::shutdown () { ProgressAdaptor *a = adaptor (); if (a) { @@ -134,7 +146,6 @@ Progress::set_desc (const std::string &d) } } - } void @@ -181,6 +192,14 @@ RelativeProgress::RelativeProgress (const std::string &desc, size_t max_count, s m_format = "%.0f%%"; m_unit = double (max_count) / 100.0; m_count = 0; + m_last_count = 0; + + initialize (); +} + +RelativeProgress::~RelativeProgress () +{ + shutdown (); } double @@ -203,7 +222,8 @@ RelativeProgress & RelativeProgress::set (size_t count, bool force_yield) { m_count = count; - test (force_yield); + test (force_yield || m_count - m_last_count >= m_unit); + m_last_count = m_count; return *this; } @@ -217,6 +237,13 @@ AbsoluteProgress::AbsoluteProgress (const std::string &desc, size_t yield_interv m_unit = 1.0; m_format_unit = 0.0; m_count = 0; + + initialize (); +} + +AbsoluteProgress::~AbsoluteProgress () +{ + shutdown (); } double diff --git a/src/tl/tl/tlProgress.h b/src/tl/tl/tlProgress.h index aa79e4e86..1f41abb43 100644 --- a/src/tl/tl/tlProgress.h +++ b/src/tl/tl/tlProgress.h @@ -29,6 +29,7 @@ #include #include "tlException.h" #include "tlTimer.h" +#include "tlList.h" class QWidget; @@ -105,6 +106,7 @@ class Progress; */ class TL_PUBLIC Progress + : public tl::list_node { public: /** @@ -203,6 +205,16 @@ protected: */ void test (bool force_yield = false); + /** + * @brief This method needs to be called by all derived classes after initialization has happened + */ + void initialize (); + + /** + * @brief This method needs to be called by all derived classes in the destructor + */ + void shutdown (); + private: friend class ProgressAdaptor; @@ -241,6 +253,11 @@ public: */ RelativeProgress (const std::string &desc, size_t max_count = 0, size_t yield_interval = 1000); + /** + * @brief Destructor + */ + ~RelativeProgress (); + /** * @brief Delivers the current progress as a string */ @@ -283,6 +300,7 @@ private: std::string m_format; size_t m_count; + size_t m_last_count; double m_unit; }; @@ -309,6 +327,11 @@ public: */ AbsoluteProgress (const std::string &desc, size_t yield_interval = 1000); + /** + * @brief Destructor + */ + ~AbsoluteProgress (); + /** * @brief Delivers the current progress as a string */ diff --git a/src/tl/unit_tests/tlListTests.cc b/src/tl/unit_tests/tlListTests.cc index f098aaa7c..5fde89b69 100644 --- a/src/tl/unit_tests/tlListTests.cc +++ b/src/tl/unit_tests/tlListTests.cc @@ -27,9 +27,13 @@ namespace { +static size_t obj_count = 0; + struct MyClass1 : public tl::list_node { - MyClass1 (int _n) : n (_n) { } + MyClass1 (int _n) : n (_n) { ++obj_count; } + MyClass1 (const MyClass1 &other) : n (other.n) { ++obj_count; } + ~MyClass1 () { --obj_count; } int n; bool operator== (const MyClass1 &other) const { return n == other.n; } bool operator< (const MyClass1 &other) const { return n < other.n; } @@ -37,7 +41,8 @@ struct MyClass1 : public tl::list_node struct MyClass2 : public tl::list_node { - MyClass2 (int _n) : n (_n) { } + MyClass2 (int _n) : n (_n) { ++obj_count; } + ~MyClass2 () { --obj_count; } int n; public: MyClass2 (const MyClass2 &other); @@ -167,6 +172,8 @@ static std::string l2srm_nc (tl::list &l) TEST(1_Basic) { + obj_count = 0; + tl::list l1, l2; EXPECT_EQ (l1.empty (), true); @@ -255,115 +262,132 @@ TEST(1_Basic) EXPECT_EQ (l2s (l3), "17,1"); EXPECT_EQ (l2sr (l3), "1,17"); EXPECT_EQ (l3.size (), size_t (2)); + + l1.clear (); + l2.clear (); + l3.clear (); + EXPECT_EQ (obj_count, size_t (0)); } TEST(2_BasicNoCopy) { - tl::list l1, l2, l3; + { + obj_count = 0; - EXPECT_EQ (l1.empty (), true); - EXPECT_EQ (l1.size (), size_t (0)); - EXPECT_EQ (l2s (l1), ""); - EXPECT_EQ (l2sr (l1), ""); + MyClass2 mc2 (42); // will not be owned + tl::list l1, l2, l3; - l1.push_back (new MyClass2 (17)); - EXPECT_EQ (l1.empty (), false); - EXPECT_EQ (l1.size (), size_t (1)); - EXPECT_EQ (l2s (l1), "17"); - EXPECT_EQ (l2sr (l1), "17"); + EXPECT_EQ (l1.empty (), true); + EXPECT_EQ (l1.size (), size_t (0)); + EXPECT_EQ (l2s (l1), ""); + EXPECT_EQ (l2sr (l1), ""); - l1.push_back (new MyClass2 (42)); - EXPECT_EQ (l1.empty (), false); - EXPECT_EQ (l1.size (), size_t (2)); - EXPECT_EQ (l2s (l1), "17,42"); - EXPECT_EQ (l2sr (l1), "42,17"); + l1.push_back (new MyClass2 (17)); + EXPECT_EQ (l1.empty (), false); + EXPECT_EQ (l1.size (), size_t (1)); + EXPECT_EQ (l2s (l1), "17"); + EXPECT_EQ (l2sr (l1), "17"); - delete l1.first (); - EXPECT_EQ (l1.empty (), false); - EXPECT_EQ (l1.size (), size_t (1)); - EXPECT_EQ (l2s (l1), "42"); - EXPECT_EQ (l2sr (l1), "42"); + l1.push_back (mc2); + EXPECT_EQ (l1.empty (), false); + EXPECT_EQ (l1.size (), size_t (2)); + EXPECT_EQ (l2s (l1), "17,42"); + EXPECT_EQ (l2sr (l1), "42,17"); - l1.clear (); - EXPECT_EQ (l1.empty (), true); - EXPECT_EQ (l1.size (), size_t (0)); - EXPECT_EQ (l2s (l1), ""); - EXPECT_EQ (l2sr (l1), ""); + delete l1.first (); + EXPECT_EQ (l1.empty (), false); + EXPECT_EQ (l1.size (), size_t (1)); + EXPECT_EQ (l2s (l1), "42"); + EXPECT_EQ (l2sr (l1), "42"); - l2.push_back (new MyClass2 (17)); - l2.push_back (new MyClass2 (42)); + l1.clear (); + EXPECT_EQ (l1.empty (), true); + EXPECT_EQ (l1.size (), size_t (0)); + EXPECT_EQ (l2s (l1), ""); + EXPECT_EQ (l2sr (l1), ""); - EXPECT_EQ (l2s (l2), "17,42"); - EXPECT_EQ (l2sr (l2), "42,17"); - l2.pop_back (); - EXPECT_EQ (l2s (l2), "17"); - EXPECT_EQ (l2sr (l2), "17"); + l2.push_back (new MyClass2 (17)); + l2.push_back (new MyClass2 (42)); - EXPECT_EQ (l2 == l3, false); - EXPECT_EQ (l2 != l3, true); - EXPECT_EQ (l2 < l3, false); + EXPECT_EQ (l2s (l2), "17,42"); + EXPECT_EQ (l2sr (l2), "42,17"); + l2.pop_back (); + EXPECT_EQ (l2s (l2), "17"); + EXPECT_EQ (l2sr (l2), "17"); - l3.push_back (new MyClass2 (17)); - EXPECT_EQ (l2 == l3, true); - EXPECT_EQ (l2 != l3, false); - EXPECT_EQ (l2 < l3, false); + EXPECT_EQ (l2 == l3, false); + EXPECT_EQ (l2 != l3, true); + EXPECT_EQ (l2 < l3, false); - l3.push_back (new MyClass2 (42)); - EXPECT_EQ (l2 == l3, false); - EXPECT_EQ (l2 != l3, true); - EXPECT_EQ (l2 < l3, true); + l3.push_back (new MyClass2 (17)); + EXPECT_EQ (l2 == l3, true); + EXPECT_EQ (l2 != l3, false); + EXPECT_EQ (l2 < l3, false); - l3.push_back (new MyClass2 (2)); - l3.push_front (new MyClass2 (1)); - EXPECT_EQ (l2 == l3, false); - EXPECT_EQ (l2 != l3, true); - EXPECT_EQ (l2 < l3, false); + l3.push_back (new MyClass2 (42)); + EXPECT_EQ (l2 == l3, false); + EXPECT_EQ (l2 != l3, true); + EXPECT_EQ (l2 < l3, true); - EXPECT_EQ (l2s (l3), "1,17,42,2"); - EXPECT_EQ (l2srm (l3), "1,17,42,2"); - EXPECT_EQ (l2sm (l3), "2,42,17,1"); - EXPECT_EQ (l2sr (l3), "2,42,17,1"); - EXPECT_EQ (l2s_nc (l3), "1,17,42,2"); - EXPECT_EQ (l2srm_nc (l3), "1,17,42,2"); - EXPECT_EQ (l2sm_nc (l3), "2,42,17,1"); - EXPECT_EQ (l2sr_nc (l3), "2,42,17,1"); - EXPECT_EQ (l3.size (), size_t (4)); + l3.push_back (new MyClass2 (2)); + l3.push_front (new MyClass2 (1)); + EXPECT_EQ (l2 == l3, false); + EXPECT_EQ (l2 != l3, true); + EXPECT_EQ (l2 < l3, false); - l3.pop_back (); - EXPECT_EQ (l2s (l3), "1,17,42"); - EXPECT_EQ (l2sr (l3), "42,17,1"); - EXPECT_EQ (l3.size (), size_t (3)); + EXPECT_EQ (l2s (l3), "1,17,42,2"); + EXPECT_EQ (l2srm (l3), "1,17,42,2"); + EXPECT_EQ (l2sm (l3), "2,42,17,1"); + EXPECT_EQ (l2sr (l3), "2,42,17,1"); + EXPECT_EQ (l2s_nc (l3), "1,17,42,2"); + EXPECT_EQ (l2srm_nc (l3), "1,17,42,2"); + EXPECT_EQ (l2sm_nc (l3), "2,42,17,1"); + EXPECT_EQ (l2sr_nc (l3), "2,42,17,1"); + EXPECT_EQ (l3.size (), size_t (4)); - MyClass2 *c1; - c1 = l3.first (); - EXPECT_EQ (c1->n, 1); - c1 = c1->next (); - EXPECT_EQ (c1->n, 17); - c1 = c1->next (); - EXPECT_EQ (c1->n, 42); - EXPECT_EQ (c1->next (), 0); + l3.pop_back (); + EXPECT_EQ (l2s (l3), "1,17,42"); + EXPECT_EQ (l2sr (l3), "42,17,1"); + EXPECT_EQ (l3.size (), size_t (3)); - c1 = l3.last (); - EXPECT_EQ (c1->n, 42); - c1 = c1->prev (); - EXPECT_EQ (c1->n, 17); - c1 = c1->prev (); - EXPECT_EQ (c1->n, 1); - EXPECT_EQ (c1->prev (), 0); + MyClass2 *c1; + c1 = l3.first (); + EXPECT_EQ (c1->n, 1); + c1 = c1->next (); + EXPECT_EQ (c1->n, 17); + c1 = c1->next (); + EXPECT_EQ (c1->n, 42); + EXPECT_EQ (c1->next (), 0); - l3.pop_front (); - EXPECT_EQ (l2s (l3), "17,42"); - EXPECT_EQ (l2sr (l3), "42,17"); - EXPECT_EQ (l3.size (), size_t (2)); + c1 = l3.last (); + EXPECT_EQ (c1->n, 42); + c1 = c1->prev (); + EXPECT_EQ (c1->n, 17); + c1 = c1->prev (); + EXPECT_EQ (c1->n, 1); + EXPECT_EQ (c1->prev (), 0); - l3.push_back (new MyClass2 (1)); - EXPECT_EQ (l2s (l3), "17,42,1"); - EXPECT_EQ (l2sr (l3), "1,42,17"); - EXPECT_EQ (l3.size (), size_t (3)); + l3.pop_front (); + EXPECT_EQ (l2s (l3), "17,42"); + EXPECT_EQ (l2sr (l3), "42,17"); + EXPECT_EQ (l3.size (), size_t (2)); - c1 = l3.first ()->next (); - delete c1; - EXPECT_EQ (l2s (l3), "17,1"); - EXPECT_EQ (l2sr (l3), "1,17"); - EXPECT_EQ (l3.size (), size_t (2)); + l3.push_back (new MyClass2 (1)); + EXPECT_EQ (l2s (l3), "17,42,1"); + EXPECT_EQ (l2sr (l3), "1,42,17"); + EXPECT_EQ (l3.size (), size_t (3)); + + c1 = l3.first ()->next (); + delete c1; + EXPECT_EQ (l2s (l3), "17,1"); + EXPECT_EQ (l2sr (l3), "1,17"); + EXPECT_EQ (l3.size (), size_t (2)); + + l1.clear (); + l2.clear (); + l3.clear (); + EXPECT_EQ (obj_count, size_t (1)); // one for mc2 + } + + EXPECT_EQ (obj_count, size_t (0)); // mc2 gone as well }