From: mfranz Date: Tue, 23 Jan 2007 16:47:04 +0000 (+0000) Subject: allow listeners to remove themselves. This is done by marking them X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;ds=inline;h=22421f66871977386665f0b03a1be11c86acae63;p=flightgear.git allow listeners to remove themselves. This is done by marking them dead and letting the next NasalSys::update() remove all dead listeners. --- diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 9d04fb295..a270a27d1 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -57,6 +57,7 @@ FGNasalSys::FGNasalSys() _gcHash = naNil(); _nextGCKey = 0; // Any value will do _callCount = 0; + _purgeListeners = false; } // Does a naCall() in a new context. Wrapped here to make lock @@ -437,6 +438,21 @@ void FGNasalSys::init() loadPropertyScripts(); } +void FGNasalSys::update(double) +{ + if(_purgeListeners) { + _purgeListeners = false; + map::iterator it, end = _listener.end(); + for(it = _listener.end(); --it != end;) { + FGNasalListener *nl = it->second; + if(nl->_dead) { + _listener.erase(it); + delete nl; + } + } + } +} + // Loads the scripts found under /nasal in the global tree void FGNasalSys::loadPropertyScripts() { @@ -690,20 +706,21 @@ naRef FGNasalSys::setListener(int argc, naRef* args) naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args) { naRef id = argc > 0 ? args[0] : naNil(); - int i = int(id.num); + map::iterator it = _listener.find(int(id.num)); - if(!naIsNum(id) || _listener.find(i) == _listener.end()) { + if(!naIsNum(id) || it == _listener.end() || it->second->_dead) { naRuntimeError(c, "removelistener() with invalid listener id"); return naNil(); } - FGNasalListener *nl = _listener[i]; + FGNasalListener *nl = it->second; if(nl->_active) { - naRuntimeError(c, "trying to remove active listener"); - return naNil(); + nl->_dead = true; + _purgeListeners = true; + return naNum(-1); } - _listener.erase(i); + _listener.erase(it); delete nl; return naNum(_listener.size()); } @@ -718,7 +735,8 @@ FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler, _handler(handler), _gcKey(key), _nas(nasal), - _active(0) + _active(0), + _dead(false) { } @@ -731,7 +749,7 @@ FGNasalListener::~FGNasalListener() void FGNasalListener::valueChanged(SGPropertyNode* node) { // drop recursive listener calls - if (_active) + if(_active || _dead) return; _active++; diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx index f8a93dd25..1658350ba 100644 --- a/src/Scripting/NasalSys.hxx +++ b/src/Scripting/NasalSys.hxx @@ -19,7 +19,7 @@ public: FGNasalSys(); virtual ~FGNasalSys(); virtual void init(); - virtual void update(double dt) { /* noop */ } + virtual void update(double dt); // Loads a nasal script from an external file and inserts it as a // global module of the specified name. @@ -79,6 +79,7 @@ private: // Listener map _listener; static int _listenerId; + bool _purgeListeners; void loadPropertyScripts(); void hashset(naRef hash, const char* key, naRef val); @@ -142,6 +143,7 @@ private: int _gcKey; FGNasalSys* _nas; unsigned int _active; + bool _dead; };