_gcHash = naNil();
_nextGCKey = 0; // Any value will do
_callCount = 0;
+ _purgeListeners = false;
}
// Does a naCall() in a new context. Wrapped here to make lock
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()
{
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());
}
_handler(handler),
_gcKey(key),
_nas(nasal),
- _active(0)
+ _active(0),
+ _dead(false)
{
}
void FGNasalListener::valueChanged(SGPropertyNode* node)
{
// drop recursive listener calls
- if (_active)
+ if(_active || _dead)
return;
_active++;
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.
// Listener
map<int, FGNasalListener *> _listener;
static int _listenerId;
+ bool _purgeListeners;
void loadPropertyScripts();
void hashset(naRef hash, const char* key, naRef val);
int _gcKey;
FGNasalSys* _nas;
unsigned int _active;
+ bool _dead;
};