From a8f3e300492ce3a7b4bba6494e20688ffa8a4cdd Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 17 Apr 2021 13:50:43 +0200 Subject: [PATCH] Work on making Angelscript work threaded --- .../AngelScript/AngelScriptResolver.cpp | 2 + .../AngelScript/ContextPool.hpp | 43 +++++++++++++++---- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp b/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp index 617805f..d66986e 100644 --- a/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp +++ b/src/ScriptResolving/AngelScript/AngelScriptResolver.cpp @@ -98,6 +98,8 @@ void AngelScriptResolver::Initialize(CreatureLib::Battling::BattleLibrary* arg, } _contextPool = new ContextPool(_engine); + + asPrepareMultithread(); } void AngelScriptResolver::RegisterTypes() { diff --git a/src/ScriptResolving/AngelScript/ContextPool.hpp b/src/ScriptResolving/AngelScript/ContextPool.hpp index 6696c45..17a83c9 100644 --- a/src/ScriptResolving/AngelScript/ContextPool.hpp +++ b/src/ScriptResolving/AngelScript/ContextPool.hpp @@ -2,34 +2,61 @@ #define PKMNLIB_CONTEXTPOOL_HPP #include +#include +#include class ContextPool { - std::vector _pool; + struct CtxThreadedPoolStorage { + std::vector Pool; + std::mutex Lock; + + ~CtxThreadedPoolStorage() { + for (auto* ctx : Pool) { + ctx->Release(); + } + } + }; + + ArbUt::Dictionary _pool; asIScriptEngine* _engine; + CtxThreadedPoolStorage* GetThreadPool() { + auto id = std::this_thread::get_id(); + if (!_pool.Has(id)) { + auto t = CtxThreadedPoolStorage(); + _pool.Insert(id, new CtxThreadedPoolStorage()); + } + return _pool[id]; + } + public: ContextPool(asIScriptEngine* engine) : _engine(engine) {} ~ContextPool() { - for (auto ctx : _pool) { - ctx->Release(); + for (const auto& kv : _pool) { + delete kv.second; } } asIScriptContext* RequestContext() { // Get a context from the pool, or create a new asIScriptContext* ctx = nullptr; - if (!_pool.empty()) { - ctx = *_pool.rbegin(); - _pool.pop_back(); - } else + auto* pool = GetThreadPool(); + std::lock_guard guard(pool->Lock); + if (!pool->Pool.empty()) { + ctx = *pool->Pool.rbegin(); + pool->Pool.pop_back(); + } else { ctx = _engine->CreateContext(); + } return ctx; } void ReturnContextToPool(asIScriptContext* ctx) { ctx->Unprepare(); - _pool.push_back(ctx); + auto* pool = GetThreadPool(); + std::lock_guard guard(pool->Lock); + pool->Pool.push_back(ctx); } };