Added hierarchical progress reporting for more detailed progress.

This commit is contained in:
Matthias Koefferlein 2018-12-31 16:41:32 +01:00
parent 923e4075da
commit 37d8f0bfca
11 changed files with 241 additions and 215 deletions

View File

@ -535,7 +535,10 @@ template <class T>
void
local_clusters<T>::build_clusters (const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn)
{
db::box_scanner<T, std::pair<unsigned int, unsigned int> > bs;
bool report_progress = tl::verbosity () >= 50;
static std::string desc = tl::to_string (tr ("Building local clusters"));
db::box_scanner<T, std::pair<unsigned int, unsigned int> > bs (report_progress, desc);
typename T::tag object_tag;
db::box_convert<T> bc;
@ -1306,9 +1309,11 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &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<db::Instance, unsigned int> bs;
bool report_progress = tl::verbosity () >= 50;
db::box_scanner<db::Instance, unsigned int> bs (report_progress, desc);
for (std::vector<db::Instance>::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
bs.insert (inst.operator-> (), 0);
@ -1320,9 +1325,11 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &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<db::local_cluster<T>, unsigned int, db::Instance, unsigned int> bs2;
bool report_progress = tl::verbosity () >= 50;
db::box_scanner2<db::local_cluster<T>, unsigned int, db::Instance, unsigned int> bs2 (report_progress, desc);
for (typename connected_clusters<T>::const_iterator c = local.begin (); c != local.end (); ++c) {
bs2.insert1 (c.operator-> (), 0);

View File

@ -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;
}

View File

@ -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

View File

@ -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 <tl::Progress *>::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 <tl::Progress *>::iterator k = mp_objects.begin (); k != mp_objects.end (); ++k) {
(*k)->signal_break ();
for (tl::list<tl::Progress>::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 ());
}
}

View File

@ -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 <tl::Progress *> mp_objects;
tl::list<tl::Progress> mp_objects;
tl::Clock m_start_time;
lay::ProgressBar *mp_pb;
bool m_pw_visible;

View File

@ -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;

View File

@ -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:

View File

@ -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<C> *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<C> *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;

View File

@ -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

View File

@ -29,6 +29,7 @@
#include <string>
#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<Progress>
{
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
*/

View File

@ -27,9 +27,13 @@
namespace
{
static size_t obj_count = 0;
struct MyClass1 : public tl::list_node<MyClass1>
{
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<MyClass1>
struct MyClass2 : public tl::list_node<MyClass2>
{
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<C> &l)
TEST(1_Basic)
{
obj_count = 0;
tl::list<MyClass1> 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<MyClass2> 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<MyClass2> 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
}