]> git.mxchange.org Git - flightgear.git/commitdiff
allow listeners to remove themselves. This is done by marking them
authormfranz <mfranz>
Tue, 23 Jan 2007 16:47:04 +0000 (16:47 +0000)
committermfranz <mfranz>
Tue, 23 Jan 2007 16:47:04 +0000 (16:47 +0000)
dead and letting the next NasalSys::update() remove all dead listeners.

src/Scripting/NasalSys.cxx
src/Scripting/NasalSys.hxx

index 9d04fb2952691e5d6cadc3753ad7592faab9596e..a270a27d189934ecc0b130bb995640838a9043e3 100644 (file)
@@ -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<int, FGNasalListener *>::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<int, FGNasalListener *>::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++;
index f8a93dd2552fe9c0841c5de18580cb8eb18e6909..1658350bac6177b0c1bcfcaec8324112eda225ef 100644 (file)
@@ -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<int, FGNasalListener *> _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;
 };