1
0
Fork 0

Rework the naModLock()/naModUnlock() semantics to be more

maintainable.  The rules are simple (extension functions are called
*with* the lock, which must be dropped before calling naCall(), which
grabs it) but the tracking of when the lock was held was getting a
little confused.  Keep a "nasal call depth" count in the subsystem to
figure out whether we are making a sub-call and thus hold the lock.
This commit is contained in:
andy 2006-07-19 19:46:53 +00:00
parent c1d06064c8
commit 503cc54a93
2 changed files with 31 additions and 32 deletions

View file

@ -56,6 +56,27 @@ FGNasalSys::FGNasalSys()
_globals = naNil(); _globals = naNil();
_gcHash = naNil(); _gcHash = naNil();
_nextGCKey = 0; // Any value will do _nextGCKey = 0; // Any value will do
_callCount = 0;
}
// Does a naCall() in a new context. Wrapped here to make lock
// tracking easier. Extension functions are called with the lock, but
// we have to release it before making a new naCall(). So rather than
// drop the lock in every extension function that might call back into
// Nasal, we keep a stack depth counter here and only unlock/lock
// around the naCall if it isn't the first one.
naRef FGNasalSys::call(naRef code, naRef locals)
{
naContext ctx = naNewContext();
if(_callCount) naModUnlock();
_callCount++;
naRef result = naCall(ctx, code, 0, 0, naNil(), locals);
if(naGetError(ctx))
logError(ctx);
_callCount--;
if(_callCount) naModLock();
naFreeContext(ctx);
return result;
} }
FGNasalSys::~FGNasalSys() FGNasalSys::~FGNasalSys()
@ -79,12 +100,8 @@ bool FGNasalSys::parseAndRun(const char* sourceCode)
strlen(sourceCode)); strlen(sourceCode));
if(naIsNil(code)) if(naIsNil(code))
return false; return false;
call(code, naNil());
naCall(_context, code, 0, 0, naNil(), naNil()); return true;
if(!naGetError(_context)) return true;
logError(_context);
return false;
} }
FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name) FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
@ -515,11 +532,7 @@ void FGNasalSys::createModule(const char* moduleName, const char* fileName,
_cmdArg = (SGPropertyNode*)arg; _cmdArg = (SGPropertyNode*)arg;
naCall(_context, code, 0, 0, naNil(), locals); call(code, locals);
if(naGetError(_context)) {
logError(_context);
return;
}
hashset(_globals, moduleName, locals); hashset(_globals, moduleName, locals);
} }
@ -527,9 +540,7 @@ void FGNasalSys::deleteModule(const char* moduleName)
{ {
naRef modname = naNewString(_context); naRef modname = naNewString(_context);
naStr_fromdata(modname, (char*)moduleName, strlen(moduleName)); naStr_fromdata(modname, (char*)moduleName, strlen(moduleName));
naModLock();
naHash_delete(_globals, modname); naHash_delete(_globals, modname);
naModUnlock();
} }
naRef FGNasalSys::parse(const char* filename, const char* buf, int len) naRef FGNasalSys::parse(const char* filename, const char* buf, int len)
@ -570,15 +581,8 @@ bool FGNasalSys::handleCommand(const SGPropertyNode* arg)
_cmdArg = (SGPropertyNode*)arg; _cmdArg = (SGPropertyNode*)arg;
// Call it! // Call it!
naModUnlock(); call(code, locals);
naRef result = naCall(c, code, 0, 0, naNil(), locals); return true;
naModLock();
bool error = naGetError(c);
if(error)
logError(c);
naFreeContext(c);
return !error;
} }
// settimer(func, dt, simtime) extension function. The first argument // settimer(func, dt, simtime) extension function. The first argument
@ -616,9 +620,7 @@ void FGNasalSys::setTimer(int argc, naRef* args)
void FGNasalSys::handleTimer(NasalTimer* t) void FGNasalSys::handleTimer(NasalTimer* t)
{ {
naCall(_context, t->handler, 0, 0, naNil(), naNil()); call(t->handler, naNil());
if(naGetError(_context))
logError(_context);
gcRelease(t->gcKey); gcRelease(t->gcKey);
} }
@ -720,13 +722,7 @@ void FGNasalListener::valueChanged(SGPropertyNode* node)
_active++; _active++;
_nas->_cmdArg = node; _nas->_cmdArg = node;
naContext c = naNewContext(); _nas->call(_handler, naNil());
naModUnlock();
naCall(c, _handler, 0, 0, naNil(), naNil());
naModLock();
if(naGetError(c))
_nas->logError(c);
naFreeContext(c);
_active--; _active--;
} }

View file

@ -57,6 +57,8 @@ public:
void deleteModule(const char* moduleName); void deleteModule(const char* moduleName);
naRef call(naRef code, naRef locals);
private: private:
friend class FGNasalScript; friend class FGNasalScript;
friend class FGNasalListener; friend class FGNasalListener;
@ -100,6 +102,7 @@ private:
int _nextGCKey; int _nextGCKey;
naRef _gcHash; naRef _gcHash;
int _callCount;
public: void handleTimer(NasalTimer* t); public: void handleTimer(NasalTimer* t);
}; };