diff --git a/src/xml/composite-node-observer.cpp b/src/xml/composite-node-observer.cpp index 77a1bd2fd3ba3d31b34e04a62e9abdd2803dcdab..f2ad9118d8e79fe65d80109c614e5656027ba86d 100644 --- a/src/xml/composite-node-observer.cpp +++ b/src/xml/composite-node-observer.cpp @@ -113,11 +113,8 @@ void CompositeNodeObserver::notifyElementNameChanged(Node& node, GQuark old_name } void CompositeNodeObserver::add(NodeObserver &observer) { - if (_iterating) { - _pending.push_back(ObserverRecord(observer)); - } else { - _active.push_back(ObserverRecord(observer)); - } + // does not invalidate iterators + _active.emplace_front(observer); } namespace { @@ -173,6 +170,8 @@ void CompositeNodeObserver::addListener(NodeEventVector const &vector, void *data) { Debug::EventTracker > tracker("add-listener"); + // This is a memory leak. Instead of fixing it, it might be worth refactoring all NodeEventVector + // (deprecated aggregate of function pointers) usage with the NodeObserver pattern. add(*(new VectorNodeObserver(vector, data))); } @@ -191,7 +190,7 @@ struct unmarked_record_satisfying { }; template -bool mark_one(ObserverRecordList &observers, unsigned &/*marked_count*/, +bool mark_one(ObserverRecordList &observers, unsigned &marked_count, Predicate p) { ObserverRecordList::iterator found=std::find_if( @@ -200,6 +199,7 @@ bool mark_one(ObserverRecordList &observers, unsigned &/*marked_count*/, ); if ( found != observers.end() ) { + ++marked_count; found->marked = true; return true; } else { @@ -237,20 +237,11 @@ bool is_marked(ObserverRecord const &record) { return record.marked; } void remove_all_marked(ObserverRecordList &observers, unsigned &marked_count) { - ObserverRecordList::iterator iter; - - g_assert( !observers.empty() || !marked_count ); - - while ( marked_count && observers.front().marked ) { - observers.pop_front(); - --marked_count; - } + if (marked_count) { + g_assert(!observers.empty()); - iter = observers.begin(); - while (marked_count) { - iter = Algorithms::find_if_before(iter, observers.end(), is_marked); - observers.erase_after(iter); - --marked_count; + observers.remove_if(is_marked); + marked_count = 0; } } @@ -259,9 +250,6 @@ void remove_all_marked(ObserverRecordList &observers, unsigned &marked_count) void CompositeNodeObserver::_finishIteration() { if (!--_iterating) { remove_all_marked(_active, _active_marked); - remove_all_marked(_pending, _pending_marked); - _active.insert(_active.end(), _pending.begin(), _pending.end()); - _pending.clear(); } } @@ -280,11 +268,9 @@ struct eql_observer { void CompositeNodeObserver::remove(NodeObserver &observer) { eql_observer p(observer); if (_iterating) { - mark_one(_active, _active_marked, p) || - mark_one(_pending, _pending_marked, p); + mark_one(_active, _active_marked, p); } else { - remove_one(_active, _active_marked, p) || - remove_one(_pending, _pending_marked, p); + remove_one(_active, _active_marked, p); } } @@ -312,11 +298,9 @@ void CompositeNodeObserver::removeListenerByData(void *data) { Debug::EventTracker > tracker("remove-listener-by-data"); vector_data_matches p(data); if (_iterating) { - mark_one(_active, _active_marked, p) || - mark_one(_pending, _pending_marked, p); + mark_one(_active, _active_marked, p); } else { - remove_one(_active, _active_marked, p) || - remove_one(_pending, _pending_marked, p); + remove_one(_active, _active_marked, p); } } diff --git a/src/xml/composite-node-observer.h b/src/xml/composite-node-observer.h index 96f1c9144b7032fce2c3d668bccebf861c2fe038..9a2f7a2a60739b2c8e7e09ec42507a8dc894dec0 100644 --- a/src/xml/composite-node-observer.h +++ b/src/xml/composite-node-observer.h @@ -13,9 +13,10 @@ #ifndef SEEN_INKSCAPE_XML_COMPOSITE_NODE_OBSERVER_H #define SEEN_INKSCAPE_XML_COMPOSITE_NODE_OBSERVER_H +#include "inkgc/gc-alloc.h" #include "inkgc/gc-managed.h" #include "xml/node-observer.h" -#include "util/list-container.h" +#include namespace Inkscape { @@ -39,10 +40,11 @@ public: NodeObserver &observer; bool marked; //< if marked for removal }; - typedef Util::ListContainer ObserverRecordList; + typedef std::forward_list> + ObserverRecordList; CompositeNodeObserver() - : _iterating(0), _active_marked(0), _pending_marked(0) {} + : _iterating(0), _active_marked(0) {} /** * @brief Add an observer to the list @@ -86,8 +88,6 @@ private: unsigned _iterating; ObserverRecordList _active; unsigned _active_marked; - ObserverRecordList _pending; - unsigned _pending_marked; void _startIteration() { ++_iterating; } void _finishIteration();