]> git.mxchange.org Git - flightgear.git/blobdiff - src/Scripting/NasalSys.cxx
allow listeners to remove themselves. This is done by marking them
[flightgear.git] / src / Scripting / NasalSys.cxx
index c486ce90ceef9cf55041011757bac05f6efa699e..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
@@ -82,7 +83,7 @@ naRef FGNasalSys::call(naRef code, naRef locals)
 FGNasalSys::~FGNasalSys()
 {
     map<int, FGNasalListener *>::iterator it, end = _listener.end();
-    for (it = _listener.begin(); it != end; ++it)
+    for(it = _listener.begin(); it != end; ++it)
         delete it->second;
 
     // Nasal doesn't have a "destroy context" API yet. :(
@@ -426,12 +427,32 @@ void FGNasalSys::init()
         loadModule(fullpath, file.base().c_str());
     }
     ulCloseDir(dir);
-    fgSetBool("/sim/signals/nasal-dir-initialized", true);
+
+    // set signal and remove node to avoid restoring at reinit
+    const char *s = "nasal-dir-initialized";
+    SGPropertyNode *signal = fgGetNode("/sim/signals", true);
+    signal->setBoolValue(s, true);
+    signal->removeChildren(s);
 
     // Pull scripts out of the property tree, too
     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()
 {
@@ -662,7 +683,7 @@ naRef FGNasalSys::setListener(int argc, naRef* args)
     else if(naIsGhost(prop)) node = *(SGPropertyNode_ptr*)naGhost_ptr(prop);
     else return naNil();
 
-    if (node->isTied())
+    if(node->isTied())
         SG_LOG(SG_NASAL, SG_DEBUG, "Attaching listener to tied property " <<
                 node->getPath());
 
@@ -685,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());
 }
@@ -713,7 +735,8 @@ FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler,
     _handler(handler),
     _gcKey(key),
     _nas(nasal),
-    _active(0)
+    _active(0),
+    _dead(false)
 {
 }
 
@@ -726,7 +749,7 @@ FGNasalListener::~FGNasalListener()
 void FGNasalListener::valueChanged(SGPropertyNode* node)
 {
     // drop recursive listener calls
-    if (_active)
+    if(_active || _dead)
         return;
 
     _active++;
@@ -747,12 +770,12 @@ void FGNasalModelData::modelLoaded(const string& path, SGPropertyNode *prop,
                                    osg::Node *)
 {
     SGPropertyNode *n = prop->getNode("nasal"), *load;
-    if (!n)
+    if(!n)
         return;
 
     load = n->getNode("load");
     _unload = n->getNode("unload");
-    if (!load && !_unload)
+    if(!load && !_unload)
         return;
 
     _module = path;
@@ -763,17 +786,17 @@ void FGNasalModelData::modelLoaded(const string& path, SGPropertyNode *prop,
 
 FGNasalModelData::~FGNasalModelData()
 {
-    if (_module.empty())
+    if(_module.empty())
         return;
 
     FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
-    if (!nas) {
+    if(!nas) {
         SG_LOG(SG_NASAL, SG_ALERT, "Trying to run an <unload> script "
                 "without Nasal subsystem present.");
         return;
     }
 
-    if (_unload) {
+    if(_unload) {
         const char *s = _unload->getStringValue();
         nas->createModule(_module.c_str(), _module.c_str(), s, strlen(s));
     }