From: James Turner Date: Sun, 6 Oct 2013 16:36:19 +0000 (+0100) Subject: Reset: Nasal can be shutdown. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=881df711ba5be8a8c0bc65f2126a0dcb63865df9;p=flightgear.git Reset: Nasal can be shutdown. Also guard against duplicate init of cppbind wrapped classes. --- diff --git a/src/GUI/FileDialog.cxx b/src/GUI/FileDialog.cxx index 33f10838b..2312960cb 100644 --- a/src/GUI/FileDialog.cxx +++ b/src/GUI/FileDialog.cxx @@ -152,17 +152,19 @@ static naRef f_createFileDialog(naContext c, naRef me, int argc, naRef* args) void postinitNasalGUI(naRef globals, naContext c) { - NasalFileDialog::init("gui._FileDialog") - .member("title", &FGFileDialog::getTitle, &FGFileDialog::setTitle) - .member("button", &FGFileDialog::getButton, &FGFileDialog::setButton) - .member("directory", &FGFileDialog::getDirectory, &FGFileDialog::setDirectory) - .member("show_hidden", &FGFileDialog::showHidden, &FGFileDialog::setShowHidden) - .member("placeholder", &FGFileDialog::getPlaceholder, &FGFileDialog::setPlaceholderName) - .member("pattern", &FGFileDialog::filterPatterns, &FGFileDialog::setFilterPatterns) - .method("open", &FGFileDialog::exec) - .method("close", &FGFileDialog::close) - .method("setCallback", &FGFileDialog::setCallbackFromNasal); - + if (!NasalFileDialog::isInit()) { + NasalFileDialog::init("gui._FileDialog") + .member("title", &FGFileDialog::getTitle, &FGFileDialog::setTitle) + .member("button", &FGFileDialog::getButton, &FGFileDialog::setButton) + .member("directory", &FGFileDialog::getDirectory, &FGFileDialog::setDirectory) + .member("show_hidden", &FGFileDialog::showHidden, &FGFileDialog::setShowHidden) + .member("placeholder", &FGFileDialog::getPlaceholder, &FGFileDialog::setPlaceholderName) + .member("pattern", &FGFileDialog::filterPatterns, &FGFileDialog::setFilterPatterns) + .method("open", &FGFileDialog::exec) + .method("close", &FGFileDialog::close) + .method("setCallback", &FGFileDialog::setCallbackFromNasal); + } + nasal::Hash guiModule = nasal::Hash(globals, c).get("gui"); guiModule.set("FILE_DIALOG_OPEN_FILE", (int) FGFileDialog::USE_OPEN_FILE); diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx index 3e57389dd..8ea979998 100644 --- a/src/Scripting/NasalCanvas.cxx +++ b/src/Scripting/NasalCanvas.cxx @@ -204,7 +204,9 @@ naRef to_nasal_helper(naContext c, const sc::ElementWeakPtr& el) naRef initNasalCanvas(naRef globals, naContext c) { - NasalEvent::init("canvas.Event") + if (!NasalEvent::isInit()) { + + NasalEvent::init("canvas.Event") .member("type", &sc::Event::getTypeString) .member("target", &sc::Event::getTarget) .member("currentTarget", &sc::Event::getCurrentTarget) @@ -245,7 +247,8 @@ naRef initNasalCanvas(naRef globals, naContext c) .bases() .member("_node_ghost", &elementGetNode) .method("_getCanvasDecoration", &canvas::Window::getCanvasDecoration); - + } + nasal::Hash globals_module(globals, c), canvas_module = globals_module.createHash("canvas"); diff --git a/src/Scripting/NasalHTTP.cxx b/src/Scripting/NasalHTTP.cxx index 344a87688..fbee30a0f 100644 --- a/src/Scripting/NasalHTTP.cxx +++ b/src/Scripting/NasalHTTP.cxx @@ -81,6 +81,8 @@ static naRef f_http_load(const nasal::CallContext& ctx) //------------------------------------------------------------------------------ naRef initNasalHTTP(naRef globals, naContext c) { + if (!NasalRequest::isInit()) { + using simgear::HTTP::Request; NasalRequest::init("http.Request") .member("url", &Request::url) @@ -107,6 +109,8 @@ naRef initNasalHTTP(naRef globals, naContext c) .bases() .member("response", &MemoryRequest::responseBody); + } + nasal::Hash globals_module(globals, c), http = globals_module.createHash("http"); diff --git a/src/Scripting/NasalPositioned.cxx b/src/Scripting/NasalPositioned.cxx index 1d2b41402..6e64bdb4b 100644 --- a/src/Scripting/NasalPositioned.cxx +++ b/src/Scripting/NasalPositioned.cxx @@ -1813,6 +1813,7 @@ private: int _gcSaveKey; }; + class NasalFPDelegateFactory : public FlightPlan::DelegateFactory { public: @@ -1823,7 +1824,7 @@ public: _gcSaveKey = _nasal->gcSave(_func); } - ~NasalFPDelegateFactory() + virtual ~NasalFPDelegateFactory() { _nasal->gcRelease(_gcSaveKey); } @@ -1845,6 +1846,20 @@ private: int _gcSaveKey; }; +static std::vector static_nasalDelegateFactories; + +void shutdownNasalPositioned() +{ + std::vector::iterator it; + for (it = static_nasalDelegateFactories.begin(); + it != static_nasalDelegateFactories.end(); ++it) + { + FlightPlan::unregisterDelegateFactory(*it); + delete (*it); + } + static_nasalDelegateFactories.clear(); +} + static naRef f_registerFPDelegate(naContext c, naRef me, int argc, naRef* args) { if ((argc < 1) || !naIsFunc(args[0])) { @@ -1853,7 +1868,7 @@ static naRef f_registerFPDelegate(naContext c, naRef me, int argc, naRef* args) NasalFPDelegateFactory* factory = new NasalFPDelegateFactory(args[0]); FlightPlan::registerDelegateFactory(factory); - + static_nasalDelegateFactories.push_back(factory); return naNil(); } diff --git a/src/Scripting/NasalPositioned.hxx b/src/Scripting/NasalPositioned.hxx index f30ee6fc8..7df6608b3 100644 --- a/src/Scripting/NasalPositioned.hxx +++ b/src/Scripting/NasalPositioned.hxx @@ -31,5 +31,6 @@ bool geodFromHash(naRef ref, SGGeod& result); naRef initNasalPositioned(naRef globals, naContext c); naRef initNasalPositioned_cppbind(naRef globals, naContext c); void postinitNasalPositioned(naRef globals, naContext c); +void shutdownNasalPositioned(); #endif // of SCRIPTING_NASAL_POSITIONED_HXX diff --git a/src/Scripting/NasalPositioned_cppbind.cxx b/src/Scripting/NasalPositioned_cppbind.cxx index 8d51624a8..cc3568c4b 100644 --- a/src/Scripting/NasalPositioned_cppbind.cxx +++ b/src/Scripting/NasalPositioned_cppbind.cxx @@ -459,6 +459,8 @@ static naRef f_sortByRange(nasal::CallContext ctx) //------------------------------------------------------------------------------ naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c) { + if (!NasalPositioned::isInit()) { + NasalPositioned::init("Positioned") .member("id", &FGPositioned::ident) .member("ident", &FGPositioned::ident) // TODO to we really need id and ident? @@ -502,6 +504,7 @@ naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c) .method("getStar", &FGAirport::findSTARWithIdent) .method("getIAP", &FGAirport::findApproachWithIdent) .method("tostring", &FGAirport::toString); + } nasal::Hash globals(globalsRef, c), positioned( globals.createHash("positioned") ); diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 24a0ecdbf..0b3422472 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -246,13 +246,6 @@ naRef FGNasalSys::callMethod(naRef code, naRef self, int argc, naRef* args, naRe FGNasalSys::~FGNasalSys() { nasalSys = 0; - map::iterator it, end = _listener.end(); - for(it = _listener.begin(); it != end; ++it) - delete it->second; - - naFreeContext(_context); - _globals = naNil(); - _string = naNil(); } bool FGNasalSys::parseAndRun(const char* sourceCode) @@ -601,10 +594,12 @@ static naRef f_findDataDir(naContext c, naRef me, int argc, naRef* args) class NasalCommand : public SGCommandMgr::Command { public: - NasalCommand(FGNasalSys* sys, naRef f) : + NasalCommand(FGNasalSys* sys, naRef f, const std::string& name) : _sys(sys), - _func(f) + _func(f), + _name(name) { + globals->get_commands()->addCommandObject(_name, this); _gcRoot = sys->gcSave(f); } @@ -628,6 +623,7 @@ private: FGNasalSys* _sys; naRef _func; int _gcRoot; + std::string _name; }; static naRef f_addCommand(naContext c, naRef me, int argc, naRef* args) @@ -635,20 +631,16 @@ static naRef f_addCommand(naContext c, naRef me, int argc, naRef* args) if(argc != 2 || !naIsString(args[0]) || !naIsFunc(args[1])) naRuntimeError(c, "bad arguments to addcommand()"); - naRef func = args[1]; - NasalCommand* cmd = new NasalCommand(nasalSys, func); - globals->get_commands()->addCommandObject(naStr_data(args[0]), cmd); + nasalSys->addCommand(args[1], naStr_data(args[0])); return naNil(); } static naRef f_removeCommand(naContext c, naRef me, int argc, naRef* args) { - SGCommandMgr::Command* cmd = globals->get_commands()->getCommand(naStr_data(args[0])); - - // SGCommandMgr::Command* cmd = globals->get_commands()->removeCommand(naStr_data(args[0])) - - delete cmd; + if ((argc < 1) || !naIsString(args[0])) + naRuntimeError(c, "bad argument to removecommand()"); + globals->get_commands()->removeCommand(naStr_data(args[0])); return naNil(); } @@ -782,13 +774,15 @@ void FGNasalSys::init() initNasalCondition(_globals, _context); initNasalHTTP(_globals, _context); - NasalTimerObj::init("Timer") - .method("start", &TimerObj::start) - .method("stop", &TimerObj::stop) - .method("restart", &TimerObj::restart) - .member("singleShot", &TimerObj::isSingleShot, &TimerObj::setSingleShot) - .member("isRunning", &TimerObj::isRunning); - + if (!NasalTimerObj::isInit()) { + NasalTimerObj::init("Timer") + .method("start", &TimerObj::start) + .method("stop", &TimerObj::stop) + .method("restart", &TimerObj::restart) + .member("singleShot", &TimerObj::isSingleShot, &TimerObj::setSingleShot) + .member("isRunning", &TimerObj::isRunning); + } + // Now load the various source files in the Nasal directory simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal")); loadScriptDirectory(nasalDir); @@ -816,6 +810,36 @@ void FGNasalSys::init() postinitNasalGUI(_globals, _context); } +void FGNasalSys::shutdown() +{ + shutdownNasalPositioned(); + + map::iterator it, end = _listener.end(); + for(it = _listener.begin(); it != end; ++it) + delete it->second; + _listener.clear(); + + NasalCommandDict::iterator j = _commands.begin(); + for (; j != _commands.end(); ++j) { + globals->get_commands()->removeCommand(j->first); + } + _commands.clear(); + + naClearSaved(); + + _string = naNil(); // will be freed by _context + naFreeContext(_context); + + //setWatchedRef(_globals); + + // remove the recursive reference in globals + hashset(_globals, "globals", naNil()); + _globals = naNil(); + + naGC(); + +} + naRef FGNasalSys::wrappedPropsNode(SGPropertyNode* aProps) { static naRef wrapNodeFunc = naNil(); @@ -1251,6 +1275,30 @@ void FGNasalSys::registerToUnload(FGNasalModelData *data) _unloadList.push(data); } +void FGNasalSys::addCommand(naRef func, const std::string& name) +{ + if (_commands.find(name) != _commands.end()) { + SG_LOG(SG_NASAL, SG_WARN, "duplicate add of command:" << name); + return; + } + + NasalCommand* cmd = new NasalCommand(this, func, name); + _commands[name] = cmd; +} + +void FGNasalSys::removeCommand(const std::string& name) +{ + NasalCommandDict::iterator it = _commands.find(name); + if (it == _commands.end()) { + SG_LOG(SG_NASAL, SG_WARN, "remove of unknwon command:" << name); + return; + } + + // will delete the NasalCommand instance + globals->get_commands()->removeCommand(name); + _commands.erase(it); +} + ////////////////////////////////////////////////////////////////////////// // FGNasalListener class. diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx index b5b3d00d4..1ce862c78 100644 --- a/src/Scripting/NasalSys.hxx +++ b/src/Scripting/NasalSys.hxx @@ -21,6 +21,7 @@ class FGNasalScript; class FGNasalListener; class SGCondition; class FGNasalModelData; +class NasalCommand; namespace simgear { class BufferedLogCallback; } @@ -33,6 +34,8 @@ public: FGNasalSys(); virtual ~FGNasalSys(); virtual void init(); + virtual void shutdown(); + virtual void update(double dt); // Loads a nasal script from an external file and inserts it as a @@ -84,6 +87,9 @@ public: void deleteModule(const char* moduleName); + void addCommand(naRef func, const std::string& name); + void removeCommand(const std::string& name); + /** * Set member of specified hash to given value */ @@ -173,6 +179,9 @@ private: SGPropertyNode_ptr _cmdArg; simgear::BufferedLogCallback* _log; + + typedef std::map NasalCommandDict; + NasalCommandDict _commands; public: void handleTimer(NasalTimer* t); };