From aac581d00d4efa8c3b03fd802f22457d4127e23f Mon Sep 17 00:00:00 2001 From: pixel Date: Wed, 1 Feb 2006 18:32:25 +0000 Subject: Adding widgets new/delete scheduling - avoiding multithreading glitches. --- lib/widgets.cc | 75 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 19 deletions(-) (limited to 'lib/widgets.cc') diff --git a/lib/widgets.cc b/lib/widgets.cc index 1f98597..02b6d6f 100644 --- a/lib/widgets.cc +++ b/lib/widgets.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: widgets.cc,v 1.17 2006-01-31 17:02:39 pixel Exp $ */ +/* $Id: widgets.cc,v 1.18 2006-02-01 18:32:26 pixel Exp $ */ #include #include @@ -39,8 +39,9 @@ mogltk::widget * dragged_widget = 0; std::vector out_move, out_click; std::vector mogltk::widget::timed_events; -std::vector to_delete; - +std::vector mogltk::widget::add_list; +std::vector mogltk::widget::del_list; +bool mogltk::widget::in_delete_loop = false; class widget_mouse_event : public mogltk::engine::mouseevent { public: @@ -211,15 +212,24 @@ mogltk::widget * mogltk::widget::focused = 0; mogltk::widget::widget(widget * _father, int _x, int _y, int _sx, int _sy, int _type, String _name, mogltk::shape * _sh) : x(_x), y(_y), sx(_sx), sy(_sy), father(_father), prev(0), child(0), last(0), panel(0), type(_type), name(_name), sh(_sh), exclusive(0), visible(true), enabled(true) { + LOCK; + add_list.push_back(this); + UNLOCK; if (!father) { - root = this; - father = this; - next = 0; x = 0; y = 0; sx = engine::base_o->GetWidth(); sy = engine::base_o->GetHeight(); + } +} + +void mogltk::widget::linkme() { + LOCK; + if (!father) { + root = this; + father = this; + next = 0; } else { next = father->child; if (next) @@ -234,9 +244,12 @@ mogltk::widget::widget(widget * _father, int _x, int _y, int _sx, int _sy, int _ computeabs(); } -mogltk::widget::~widget() { +mogltk::widget::~widget() throw (GeneralException) { while(child) delete child; + + if (!in_delete_loop) + throw GeneralException("Invalid wild delete."); LOCK; if (prev) @@ -266,14 +279,19 @@ mogltk::widget::~widget() { } } -#if 0 - for (iw = to_delete.begin(); iw != to_delete.end(); iw++) { + for (iw = del_list.begin(); iw != del_list.end(); iw++) { if (*iw == this) { - to_delete.erase(iw); - iw = to_delete.begin(); + del_list.erase(iw); + iw = del_list.begin(); + } + } + + for (iw = add_list.begin(); iw != add_list.end(); iw++) { + if (*iw == this) { + add_list.erase(iw); + iw = add_list.begin(); } } -#endif for (it = timed_events.begin(); it != timed_events.end(); it++) { if (it->w == this) { @@ -414,7 +432,8 @@ void mogltk::widget::fulldraw() { mogltk::ColorP::Min = BLACK; mogltk::ColorP::Min.A = 0; - root->idraw(); + if (root) + root->idraw(); if (!was2D) mogltk::engine::glbase_o->Leave2DMode(); @@ -647,7 +666,9 @@ void mogltk::widget::center(bool cx, bool cy) { } void mogltk::widget::delete_me() { - to_delete.push_back(this); + LOCK; + del_list.push_back(this); + UNLOCK; } @@ -661,7 +682,7 @@ void mogltk::widget::delete_me() { mogltk::widgets::Root::Root(mogltk::shape * sh, mogltk::widgets::drawer * _dr) : widget(0, 0, 0, 0, 0, 0, "Root", sh), dr(_dr) { if (engine::root) - delete engine::root; + engine::root->delete_me(); engine::root = this; } @@ -806,7 +827,7 @@ class SmartBoxCloseAction : public mogltk::widgets::action { public: SmartBoxCloseAction(mogltk::widget * _parent) : parent(_parent) { } virtual void do_action(mogltk::widget *) { - delete parent; + parent->delete_me(); delete this; } private: @@ -890,7 +911,8 @@ void mogltk::widget::mainloop() { int mx, my; while (!end_event_loop && !engine::quitrequested()) { - root->fulldraw(); + if (root) + root->fulldraw(); mx = mogltk::engine::mouseX(); my = mogltk::engine::mouseY(); @@ -904,10 +926,25 @@ void mogltk::widget::mainloop() { engine::base_o->Flip(); widget::check_timed_events(); - for (std::vector::iterator i = to_delete.begin(); i != to_delete.end(); i++) { + LOCK; + std::vector del_list_copy = del_list; + del_list.clear(); + UNLOCK; + + in_delete_loop = true; + for (std::vector::iterator i = del_list_copy.begin(); i != del_list_copy.end(); i++) { delete *i; } - to_delete.clear(); + in_delete_loop = false; + + LOCK; + std::vector add_list_copy = add_list; + add_list.clear(); + UNLOCK; + + for (std::vector::iterator i = add_list_copy.begin(); i != add_list_copy.end(); i++) { + (*i)->linkme(); + } } delete mouse; -- cgit v1.2.3