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:
parent
016750c865
commit
22421f6687
2 changed files with 29 additions and 9 deletions
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue