1
0
Fork 0

allow listeners to remove themselves. This is done by marking them

dead and letting the next NasalSys::update() remove all dead listeners.
This commit is contained in:
mfranz 2007-01-23 16:47:04 +00:00
parent 016750c865
commit 22421f6687
2 changed files with 29 additions and 9 deletions

View file

@ -57,6 +57,7 @@ FGNasalSys::FGNasalSys()
_gcHash = naNil(); _gcHash = naNil();
_nextGCKey = 0; // Any value will do _nextGCKey = 0; // Any value will do
_callCount = 0; _callCount = 0;
_purgeListeners = false;
} }
// Does a naCall() in a new context. Wrapped here to make lock // Does a naCall() in a new context. Wrapped here to make lock
@ -437,6 +438,21 @@ void FGNasalSys::init()
loadPropertyScripts(); 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 // Loads the scripts found under /nasal in the global tree
void FGNasalSys::loadPropertyScripts() void FGNasalSys::loadPropertyScripts()
{ {
@ -690,20 +706,21 @@ naRef FGNasalSys::setListener(int argc, naRef* args)
naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args) naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
{ {
naRef id = argc > 0 ? args[0] : naNil(); 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"); naRuntimeError(c, "removelistener() with invalid listener id");
return naNil(); return naNil();
} }
FGNasalListener *nl = _listener[i]; FGNasalListener *nl = it->second;
if(nl->_active) { if(nl->_active) {
naRuntimeError(c, "trying to remove active listener"); nl->_dead = true;
return naNil(); _purgeListeners = true;
return naNum(-1);
} }
_listener.erase(i); _listener.erase(it);
delete nl; delete nl;
return naNum(_listener.size()); return naNum(_listener.size());
} }
@ -718,7 +735,8 @@ FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler,
_handler(handler), _handler(handler),
_gcKey(key), _gcKey(key),
_nas(nasal), _nas(nasal),
_active(0) _active(0),
_dead(false)
{ {
} }
@ -731,7 +749,7 @@ FGNasalListener::~FGNasalListener()
void FGNasalListener::valueChanged(SGPropertyNode* node) void FGNasalListener::valueChanged(SGPropertyNode* node)
{ {
// drop recursive listener calls // drop recursive listener calls
if (_active) if(_active || _dead)
return; return;
_active++; _active++;

View file

@ -19,7 +19,7 @@ public:
FGNasalSys(); FGNasalSys();
virtual ~FGNasalSys(); virtual ~FGNasalSys();
virtual void init(); 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 // Loads a nasal script from an external file and inserts it as a
// global module of the specified name. // global module of the specified name.
@ -79,6 +79,7 @@ private:
// Listener // Listener
map<int, FGNasalListener *> _listener; map<int, FGNasalListener *> _listener;
static int _listenerId; static int _listenerId;
bool _purgeListeners;
void loadPropertyScripts(); void loadPropertyScripts();
void hashset(naRef hash, const char* key, naRef val); void hashset(naRef hash, const char* key, naRef val);
@ -142,6 +143,7 @@ private:
int _gcKey; int _gcKey;
FGNasalSys* _nas; FGNasalSys* _nas;
unsigned int _active; unsigned int _active;
bool _dead;
}; };