86 lines
2.3 KiB
C++
86 lines
2.3 KiB
C++
#ifndef PKMNLIB_CONTEXTPOOL_HPP
|
|
#define PKMNLIB_CONTEXTPOOL_HPP
|
|
|
|
#include <angelscript.h>
|
|
#include <mutex>
|
|
#include <thread>
|
|
#include "AngelscriptUserdata.hpp"
|
|
|
|
class ContextPool {
|
|
struct CtxThreadedPoolStorage {
|
|
std::vector<asIScriptContext*> Pool;
|
|
std::mutex Lock;
|
|
|
|
~CtxThreadedPoolStorage() {
|
|
for (auto* ctx : Pool) {
|
|
ctx->Release();
|
|
}
|
|
}
|
|
};
|
|
|
|
std::mutex Lock;
|
|
ArbUt::Dictionary<std::thread::id, CtxThreadedPoolStorage*> _pool;
|
|
AngelScriptResolver* _resolver;
|
|
AngelscriptUserdata* _userData;
|
|
|
|
CtxThreadedPoolStorage* CreateThreadPool(std::thread::id id) {
|
|
std::lock_guard<std::mutex> guard(Lock);
|
|
auto tryGet = _pool.TryGet(id);
|
|
if (tryGet.has_value()) {
|
|
return tryGet->get();
|
|
}
|
|
|
|
auto p = new CtxThreadedPoolStorage();
|
|
_pool.Insert(id, p);
|
|
return p;
|
|
}
|
|
|
|
CtxThreadedPoolStorage* GetThreadPool() {
|
|
auto id = std::this_thread::get_id();
|
|
auto tryGet = _pool.TryGet(id);
|
|
if (tryGet.has_value()) {
|
|
return tryGet->get();
|
|
}
|
|
return CreateThreadPool(id);
|
|
}
|
|
|
|
public:
|
|
ContextPool(AngelScriptResolver* resolver, AngelscriptUserdata* userData)
|
|
: _resolver(resolver), _userData(userData) {}
|
|
|
|
~ContextPool() {
|
|
for (const auto& kv : _pool) {
|
|
delete kv.second;
|
|
}
|
|
}
|
|
|
|
asIScriptContext* RequestContext() {
|
|
// Get a context from the pool, or create a new
|
|
asIScriptContext* ctx = nullptr;
|
|
auto* pool = GetThreadPool();
|
|
std::lock_guard<std::mutex> guard(pool->Lock);
|
|
if (!pool->Pool.empty()) {
|
|
ctx = *pool->Pool.rbegin();
|
|
pool->Pool.pop_back();
|
|
} else {
|
|
ctx = _resolver->GetEngine()->CreateContext();
|
|
ctx->SetUserData(_userData);
|
|
}
|
|
#ifdef ANGELSCRIPT_DEBUGGER
|
|
if (_resolver->GetDebugger().HasValue()) {
|
|
_resolver->GetDebugger().GetValue()->RegisterContext(ctx);
|
|
}
|
|
#endif
|
|
return ctx;
|
|
}
|
|
|
|
void ReturnContextToPool(asIScriptContext* ctx) {
|
|
ctx->Unprepare();
|
|
auto* pool = GetThreadPool();
|
|
std::lock_guard<std::mutex> guard(pool->Lock);
|
|
pool->Pool.push_back(ctx);
|
|
}
|
|
};
|
|
|
|
#endif // PKMNLIB_CONTEXTPOOL_HPP
|