diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 6e177bb0fa..c397097321 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -63,6 +63,7 @@ add_openmw_dir (mwlua luabindings localscripts playerscripts objectbindings cellbindings asyncbindings camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings types/types types/door types/actor types/container types/weapon types/npc types/creature types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair + worker ) add_openmw_dir (mwsound diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 7a3e10ee53..05eb457301 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -49,6 +49,7 @@ #include "mwgui/windowmanagerimp.hpp" #include "mwlua/luamanagerimp.hpp" +#include "mwlua/worker.hpp" #include "mwscript/interpretercontext.hpp" #include "mwscript/scriptmanagerimp.hpp" @@ -797,98 +798,6 @@ void OMW::Engine::prepareEngine() mLuaManager->loadPermanentStorage(mCfgMgr.getUserConfigPath()); } -class OMW::Engine::LuaWorker -{ -public: - explicit LuaWorker(Engine* engine) - : mEngine(engine) - { - if (Settings::Manager::getInt("lua num threads", "Lua") > 0) - mThread = std::thread([this] { threadBody(); }); - } - - ~LuaWorker() - { - if (mThread && mThread->joinable()) - { - Log(Debug::Error) - << "Unexpected destruction of LuaWorker; likely there is an unhandled exception in the main thread."; - join(); - } - } - - void allowUpdate() - { - if (!mThread) - return; - { - std::lock_guard lk(mMutex); - mUpdateRequest = true; - } - mCV.notify_one(); - } - - void finishUpdate() - { - if (mThread) - { - std::unique_lock lk(mMutex); - mCV.wait(lk, [&] { return !mUpdateRequest; }); - } - else - update(); - } - - void join() - { - if (mThread) - { - { - std::lock_guard lk(mMutex); - mJoinRequest = true; - } - mCV.notify_one(); - mThread->join(); - } - } - -private: - void update() - { - const auto& viewer = mEngine->mViewer; - const osg::Timer_t frameStart = viewer->getStartTick(); - const unsigned int frameNumber = viewer->getFrameStamp()->getFrameNumber(); - ScopedProfile profile( - frameStart, frameNumber, *osg::Timer::instance(), *viewer->getViewerStats()); - - mEngine->mLuaManager->update(); - } - - void threadBody() - { - while (true) - { - std::unique_lock lk(mMutex); - mCV.wait(lk, [&] { return mUpdateRequest || mJoinRequest; }); - if (mJoinRequest) - break; - - update(); - - mUpdateRequest = false; - lk.unlock(); - mCV.notify_one(); - } - } - - Engine* mEngine; - std::mutex mMutex; - std::condition_variable mCV; - bool mUpdateRequest = false; - bool mJoinRequest = false; - std::optional mThread; -}; - // Initialise and enter main loop. void OMW::Engine::go() { @@ -977,7 +886,7 @@ void OMW::Engine::go() mWindowManager->executeInConsole(mStartupScript); } - LuaWorker luaWorker(this); // starts a separate lua thread if "lua num threads" > 0 + MWLua::Worker luaWorker(*mLuaManager, *mViewer); // starts a separate lua thread if "lua num threads" > 0 // Start the main rendering loop double simulationTime = 0.0; diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index cdc54c7018..61d28402c2 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -262,7 +262,6 @@ namespace OMW private: Files::ConfigurationManager& mCfgMgr; - class LuaWorker; int mGlMaxTextureImageUnits; }; } diff --git a/apps/openmw/mwlua/worker.cpp b/apps/openmw/mwlua/worker.cpp new file mode 100644 index 0000000000..0dbe78ad4b --- /dev/null +++ b/apps/openmw/mwlua/worker.cpp @@ -0,0 +1,92 @@ +#include "worker.hpp" + +#include "luamanagerimp.hpp" + +#include + +#include + +#include + +namespace MWLua +{ + Worker::Worker(LuaManager& manager, osgViewer::Viewer& viewer) + : mManager(manager) + , mViewer(viewer) + { + if (Settings::Manager::getInt("lua num threads", "Lua") > 0) + mThread = std::thread([this] { run(); }); + } + + Worker::~Worker() + { + if (mThread && mThread->joinable()) + { + Log(Debug::Error) + << "Unexpected destruction of LuaWorker; likely there is an unhandled exception in the main thread."; + join(); + } + } + + void Worker::allowUpdate() + { + if (!mThread) + return; + { + std::lock_guard lk(mMutex); + mUpdateRequest = true; + } + mCV.notify_one(); + } + + void Worker::finishUpdate() + { + if (mThread) + { + std::unique_lock lk(mMutex); + mCV.wait(lk, [&] { return !mUpdateRequest; }); + } + else + update(); + } + + void Worker::join() + { + if (mThread) + { + { + std::lock_guard lk(mMutex); + mJoinRequest = true; + } + mCV.notify_one(); + mThread->join(); + } + } + + void Worker::update() + { + const osg::Timer_t frameStart = mViewer.getStartTick(); + const unsigned int frameNumber = mViewer.getFrameStamp()->getFrameNumber(); + OMW::ScopedProfile profile( + frameStart, frameNumber, *osg::Timer::instance(), *mViewer.getViewerStats()); + + mManager.update(); + } + + void Worker::run() noexcept + { + while (true) + { + std::unique_lock lk(mMutex); + mCV.wait(lk, [&] { return mUpdateRequest || mJoinRequest; }); + if (mJoinRequest) + break; + + update(); + + mUpdateRequest = false; + lk.unlock(); + mCV.notify_one(); + } + } +} diff --git a/apps/openmw/mwlua/worker.hpp b/apps/openmw/mwlua/worker.hpp new file mode 100644 index 0000000000..fed625e1f1 --- /dev/null +++ b/apps/openmw/mwlua/worker.hpp @@ -0,0 +1,46 @@ +#ifndef OPENMW_MWLUA_WORKER_H +#define OPENMW_MWLUA_WORKER_H + +#include +#include +#include +#include + +namespace osgViewer +{ + class Viewer; +} + +namespace MWLua +{ + class LuaManager; + + class Worker + { + public: + explicit Worker(LuaManager& manager, osgViewer::Viewer& viewer); + + ~Worker(); + + void allowUpdate(); + + void finishUpdate(); + + void join(); + + private: + void update(); + + void run() noexcept; + + LuaManager& mManager; + osgViewer::Viewer& mViewer; + std::mutex mMutex; + std::condition_variable mCV; + bool mUpdateRequest = false; + bool mJoinRequest = false; + std::optional mThread; + }; +} + +#endif // OPENMW_MWLUA_LUAWORKER_H