diff --git a/src/squirrel/script_engine.cpp b/src/squirrel/script_engine.cpp index 0e3b7b1801b..b3f67c9abdd 100644 --- a/src/squirrel/script_engine.cpp +++ b/src/squirrel/script_engine.cpp @@ -24,7 +24,7 @@ #include "util/log.hpp" ScriptEngine::ScriptEngine() : - m_vm(scripting::global_vm), + m_vm(Scripting::current()->get_vm()), m_table(), m_scripts() { diff --git a/src/squirrel/script_engine.hpp b/src/squirrel/script_engine.hpp index 84b7a8f2dab..61ee34083b3 100644 --- a/src/squirrel/script_engine.hpp +++ b/src/squirrel/script_engine.hpp @@ -35,7 +35,7 @@ class ScriptEngine virtual ~ScriptEngine(); protected: - /** Expose this engine in the global_vm under 'name' */ + /** Expose this engine under 'name' */ void expose_self(const std::string& name); void unexpose_self(const std::string& name); @@ -49,7 +49,7 @@ class ScriptEngine template void expose(const std::string& name, std::unique_ptr script_object) { - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); sq_pushobject(vm, m_table); expose_object(vm, -1, std::move(script_object), name.c_str()); sq_pop(vm, 1); diff --git a/src/squirrel/scripting.cpp b/src/squirrel/scripting.cpp index 0d113db5527..35a5a29af46 100644 --- a/src/squirrel/scripting.cpp +++ b/src/squirrel/scripting.cpp @@ -61,60 +61,55 @@ void printfunc(HSQUIRRELVM, const char* fmt, ...) } // namespace -namespace scripting { - -HSQUIRRELVM global_vm = nullptr; - -} // namespace scripting - -Scripting::Scripting(bool enable_debugger) +Scripting::Scripting(bool enable_debugger) : + m_vm() { - scripting::global_vm = sq_open(64); - if(scripting::global_vm == nullptr) + m_vm = sq_open(64); + if(m_vm == nullptr) throw std::runtime_error("Couldn't initialize squirrel vm"); if(enable_debugger) { #ifdef ENABLE_SQDBG - sq_enabledebuginfo(scripting::global_vm, SQTrue); - debugger = sq_rdbg_init(scripting::global_vm, 1234, SQFalse); + sq_enabledebuginfo(m_vm, SQTrue); + debugger = sq_rdbg_init(m_vm, 1234, SQFalse); if(debugger == nullptr) - throw SquirrelError(scripting::global_vm, "Couldn't initialize squirrel debugger"); + throw SquirrelError(m_vm, "Couldn't initialize squirrel debugger"); - sq_enabledebuginfo(scripting::global_vm, SQTrue); + sq_enabledebuginfo(m_vm, SQTrue); log_info << "Waiting for debug client..." << std::endl; if(SQ_FAILED(sq_rdbg_waitforconnections(debugger))) - throw SquirrelError(scripting::global_vm, "Waiting for debug clients failed"); + throw SquirrelError(m_vm, "Waiting for debug clients failed"); log_info << "debug client connected." << std::endl; #endif } - sq_pushroottable(scripting::global_vm); - if(SQ_FAILED(sqstd_register_bloblib(scripting::global_vm))) - throw SquirrelError(scripting::global_vm, "Couldn't register blob lib"); - if(SQ_FAILED(sqstd_register_mathlib(scripting::global_vm))) - throw SquirrelError(scripting::global_vm, "Couldn't register math lib"); - if(SQ_FAILED(sqstd_register_stringlib(scripting::global_vm))) - throw SquirrelError(scripting::global_vm, "Couldn't register string lib"); + sq_pushroottable(m_vm); + if(SQ_FAILED(sqstd_register_bloblib(m_vm))) + throw SquirrelError(m_vm, "Couldn't register blob lib"); + if(SQ_FAILED(sqstd_register_mathlib(m_vm))) + throw SquirrelError(m_vm, "Couldn't register math lib"); + if(SQ_FAILED(sqstd_register_stringlib(m_vm))) + throw SquirrelError(m_vm, "Couldn't register string lib"); // remove rand and srand calls from sqstdmath, we'll provide our own - delete_table_entry(scripting::global_vm, "srand"); - delete_table_entry(scripting::global_vm, "rand"); + delete_table_entry(m_vm, "srand"); + delete_table_entry(m_vm, "rand"); // register supertux API - scripting::register_supertux_wrapper(scripting::global_vm); + scripting::register_supertux_wrapper(m_vm); - sq_pop(scripting::global_vm, 1); + sq_pop(m_vm, 1); // register print function - sq_setprintfunc(scripting::global_vm, printfunc, printfunc); + sq_setprintfunc(m_vm, printfunc, printfunc); // register default error handlers - sqstd_seterrorhandlers(scripting::global_vm); + sqstd_seterrorhandlers(m_vm); // try to load default script try { std::string filename = "scripts/default.nut"; IFileStream stream(filename); - compile_and_run(scripting::global_vm, stream, filename); + compile_and_run(m_vm, stream, filename); } catch(std::exception& e) { log_warning << "Couldn't load default.nut: " << e.what() << std::endl; } @@ -129,10 +124,7 @@ Scripting::~Scripting() } #endif - if (scripting::global_vm) - sq_close(scripting::global_vm); - - scripting::global_vm = nullptr; + sq_close(m_vm); } void diff --git a/src/squirrel/scripting.hpp b/src/squirrel/scripting.hpp index bd889fb89d2..89b1e1e0ef2 100644 --- a/src/squirrel/scripting.hpp +++ b/src/squirrel/scripting.hpp @@ -21,12 +21,6 @@ #include "util/currenton.hpp" -namespace scripting { - -extern HSQUIRRELVM global_vm; - -} // namespace scripting - class Scripting final : public Currenton { public: @@ -35,6 +29,11 @@ class Scripting final : public Currenton void update_debugger(); + HSQUIRRELVM get_vm() const { return m_vm; } + +private: + HSQUIRRELVM m_vm; + private: Scripting(const Scripting&) = delete; Scripting& operator=(const Scripting&) = delete; diff --git a/src/squirrel/thread_queue.cpp b/src/squirrel/thread_queue.cpp index 92a2ba2b1ea..78fe9178fdb 100644 --- a/src/squirrel/thread_queue.cpp +++ b/src/squirrel/thread_queue.cpp @@ -21,6 +21,7 @@ #include "util/log.hpp" ThreadQueue::ThreadQueue() : + m_vm(Scripting::current()->get_vm()), threads() { } @@ -30,18 +31,18 @@ ThreadQueue::add(HSQUIRRELVM vm) { // create a weakref to the VM HSQOBJECT vm_obj = vm_to_object(vm); - sq_pushobject(scripting::global_vm, vm_obj); - sq_weakref(scripting::global_vm, -1); + sq_pushobject(m_vm, vm_obj); + sq_weakref(m_vm, -1); HSQOBJECT object; - if(SQ_FAILED(sq_getstackobj(scripting::global_vm, -1, &object))) { - sq_pop(scripting::global_vm, 2); - throw SquirrelError(scripting::global_vm, "Couldn't get thread weakref from vm"); + if(SQ_FAILED(sq_getstackobj(m_vm, -1, &object))) { + sq_pop(m_vm, 2); + throw SquirrelError(m_vm, "Couldn't get thread weakref from vm"); } - sq_addref(scripting::global_vm, &object); + sq_addref(m_vm, &object); threads.push_back(object); - sq_pop(scripting::global_vm, 2); + sq_pop(m_vm, 2); } void @@ -56,19 +57,19 @@ ThreadQueue::wakeup() while(i != end) { HSQOBJECT object = threads[i]; - sq_pushobject(scripting::global_vm, object); - sq_getweakrefval(scripting::global_vm, -1); + sq_pushobject(m_vm, object); + sq_getweakrefval(m_vm, -1); HSQUIRRELVM scheduled_vm; - if(sq_gettype(scripting::global_vm, -1) == OT_THREAD && - SQ_SUCCEEDED(sq_getthread(scripting::global_vm, -1, &scheduled_vm))) { + if(sq_gettype(m_vm, -1) == OT_THREAD && + SQ_SUCCEEDED(sq_getthread(m_vm, -1, &scheduled_vm))) { if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) { log_warning << "Couldn't wakeup scheduled squirrel VM" << std::endl; } } - sq_release(scripting::global_vm, &object); - sq_pop(scripting::global_vm, 1); + sq_release(m_vm, &object); + sq_pop(m_vm, 1); i--; } diff --git a/src/squirrel/thread_queue.hpp b/src/squirrel/thread_queue.hpp index 6b717af2ae8..96026c46cd2 100644 --- a/src/squirrel/thread_queue.hpp +++ b/src/squirrel/thread_queue.hpp @@ -34,8 +34,14 @@ class ThreadQueue final void wakeup(); private: + HSQUIRRELVM m_vm; + typedef std::vector ThreadList; ThreadList threads; + +private: + ThreadQueue(const ThreadQueue&) = delete; + ThreadQueue& operator=(const ThreadQueue&) = delete; }; #endif diff --git a/src/squirrel/time_scheduler.cpp b/src/squirrel/time_scheduler.cpp index 53a75f96f2a..c48d2aecf74 100644 --- a/src/squirrel/time_scheduler.cpp +++ b/src/squirrel/time_scheduler.cpp @@ -24,6 +24,7 @@ TimeScheduler* TimeScheduler::instance = nullptr; TimeScheduler::TimeScheduler() : + m_vm(Scripting::current()->get_vm()), schedule() { } @@ -34,12 +35,12 @@ TimeScheduler::update(float time) while(!schedule.empty() && schedule.front().wakeup_time < time) { HSQOBJECT thread_ref = schedule.front().thread_ref; - sq_pushobject(scripting::global_vm, thread_ref); - sq_getweakrefval(scripting::global_vm, -1); + sq_pushobject(m_vm, thread_ref); + sq_getweakrefval(m_vm, -1); HSQUIRRELVM scheduled_vm; - if(sq_gettype(scripting::global_vm, -1) == OT_THREAD && - SQ_SUCCEEDED(sq_getthread(scripting::global_vm, -1, &scheduled_vm))) { + if(sq_gettype(m_vm, -1) == OT_THREAD && + SQ_SUCCEEDED(sq_getthread(m_vm, -1, &scheduled_vm))) { if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) { std::ostringstream msg; msg << "Error waking VM: "; @@ -56,8 +57,8 @@ TimeScheduler::update(float time) } } - sq_release(scripting::global_vm, &thread_ref); - sq_pop(scripting::global_vm, 2); + sq_release(m_vm, &thread_ref); + sq_pop(m_vm, 2); std::pop_heap(schedule.begin(), schedule.end()); schedule.pop_back(); @@ -69,18 +70,18 @@ TimeScheduler::schedule_thread(HSQUIRRELVM scheduled_vm, float time) { // create a weakref to the VM SQObject vm_obj = vm_to_object(scheduled_vm); - sq_pushobject(scripting::global_vm, vm_obj); - sq_weakref(scripting::global_vm, -1); + sq_pushobject(m_vm, vm_obj); + sq_weakref(m_vm, -1); ScheduleEntry entry; - if(SQ_FAILED(sq_getstackobj(scripting::global_vm, -1, & entry.thread_ref))) { - sq_pop(scripting::global_vm, 2); - throw SquirrelError(scripting::global_vm, "Couldn't get thread weakref from vm"); + if(SQ_FAILED(sq_getstackobj(m_vm, -1, & entry.thread_ref))) { + sq_pop(m_vm, 2); + throw SquirrelError(m_vm, "Couldn't get thread weakref from vm"); } entry.wakeup_time = time; - sq_addref(scripting::global_vm, & entry.thread_ref); - sq_pop(scripting::global_vm, 2); + sq_addref(m_vm, & entry.thread_ref); + sq_pop(m_vm, 2); schedule.push_back(entry); std::push_heap(schedule.begin(), schedule.end()); diff --git a/src/squirrel/time_scheduler.hpp b/src/squirrel/time_scheduler.hpp index 54150a73f4a..d545db32599 100644 --- a/src/squirrel/time_scheduler.hpp +++ b/src/squirrel/time_scheduler.hpp @@ -34,6 +34,8 @@ class TimeScheduler final static TimeScheduler* instance; private: + HSQUIRRELVM m_vm; + struct ScheduleEntry { /// weak reference to the squirrel vm object HSQOBJECT thread_ref; @@ -49,6 +51,10 @@ class TimeScheduler final typedef std::vector ScheduleHeap; ScheduleHeap schedule; + +private: + TimeScheduler(const TimeScheduler&) = delete; + TimeScheduler& operator=(const TimeScheduler&) = delete; }; #endif diff --git a/src/supertux/console.cpp b/src/supertux/console.cpp index 867ae5a6080..b53a95edd7f 100644 --- a/src/supertux/console.cpp +++ b/src/supertux/console.cpp @@ -126,9 +126,9 @@ Console::Console(ConsoleBuffer& buffer) : Console::~Console() { - if (m_vm != nullptr && scripting::global_vm != nullptr) + if (m_vm != nullptr && Scripting::current() != nullptr) { - sq_release(scripting::global_vm, &m_vm_object); + sq_release(Scripting::current()->get_vm(), &m_vm_object); } } @@ -153,7 +153,7 @@ void Console::ready_vm() { if(m_vm == nullptr) { - m_vm = scripting::global_vm; + m_vm = Scripting::current()->get_vm(); HSQUIRRELVM new_vm = sq_newthread(m_vm, 16); if(new_vm == nullptr) throw SquirrelError(m_vm, "Couldn't create new VM thread for console"); diff --git a/src/supertux/savegame.cpp b/src/supertux/savegame.cpp index 741f9076e75..96420f94d6b 100644 --- a/src/supertux/savegame.cpp +++ b/src/supertux/savegame.cpp @@ -139,7 +139,7 @@ Savegame::load() try { - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); auto doc = ReaderDocument::from_file(m_filename); auto root = doc.get_root(); @@ -194,7 +194,7 @@ Savegame::load() void Savegame::clear_state_table() { - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); // delete existing state table, if it exists sq_pushroottable(vm); @@ -237,7 +237,7 @@ Savegame::save() } } - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); Writer writer(m_filename); @@ -281,7 +281,7 @@ Savegame::get_worldmaps() { std::vector worlds; - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); SQInteger oldtop = sq_gettop(vm); try @@ -306,7 +306,7 @@ Savegame::get_worldmap_state(const std::string& name) { WorldmapState result; - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); SQInteger oldtop = sq_gettop(vm); try @@ -334,7 +334,7 @@ Savegame::get_levelsets() { std::vector results; - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); SQInteger oldtop = sq_gettop(vm); try @@ -359,7 +359,7 @@ Savegame::get_levelset_state(const std::string& basedir) { LevelsetState result; - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); SQInteger oldtop = sq_gettop(vm); try @@ -389,7 +389,7 @@ Savegame::set_levelset_state(const std::string& basedir, { LevelsetState state = get_levelset_state(basedir); - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); SQInteger oldtop = sq_gettop(vm); try diff --git a/src/worldmap/worldmap_state.cpp b/src/worldmap/worldmap_state.cpp index 97e1de89822..f4d9b5c004d 100644 --- a/src/worldmap/worldmap_state.cpp +++ b/src/worldmap/worldmap_state.cpp @@ -40,7 +40,7 @@ WorldMapState::load_state() { log_debug << "loading worldmap state" << std::endl; - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); SQInteger oldtop = sq_gettop(vm); try { @@ -184,7 +184,7 @@ WorldMapState::load_state() void WorldMapState::save_state() const { - HSQUIRRELVM vm = scripting::global_vm; + HSQUIRRELVM vm = Scripting::current()->get_vm(); SQInteger oldtop = sq_gettop(vm); try {