Make VM easily movable

This commit is contained in:
King_DuckZ 2020-04-26 12:26:39 +02:00
parent ebd455c536
commit d0be115181
2 changed files with 38 additions and 37 deletions

View file

@ -19,39 +19,55 @@ namespace wren {
void write_fn (WrenVM* wvm, const char* text) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->write_fn and cb->config_obj and cb->vm);
cb->write_fn(*cb->config_obj, cb->vm, text);
assert(cb->write_fn and cb->config_obj and cb->owner);
cb->write_fn(*cb->config_obj, cb->owner, text);
}
void error_fn (WrenVM* wvm, WrenErrorType type, const char* module, int line, const char* message) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->error_fn and cb->config_obj and cb->vm);
cb->error_fn(*cb->config_obj, cb->vm, to_error_type(type), module, line, message);
assert(cb->error_fn and cb->config_obj and cb->owner);
cb->error_fn(*cb->config_obj, cb->owner, to_error_type(type), module, line, message);
}
const char* resolve_module_fn (WrenVM* wvm, const char* importer, const char* name) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->resolve_module_fn and cb->config_obj and cb->vm);
return cb->resolve_module_fn(*cb->config_obj, cb->vm, importer, name);
assert(cb->resolve_module_fn and cb->config_obj and cb->owner);
return cb->resolve_module_fn(*cb->config_obj, cb->owner, importer, name);
}
char* load_module_fn (WrenVM* wvm, const char* name) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->load_module_fn and cb->config_obj and cb->vm);
return cb->load_module_fn(*cb->config_obj, cb->vm, name);
assert(cb->load_module_fn and cb->config_obj and cb->owner);
return cb->load_module_fn(*cb->config_obj, cb->owner, name);
}
} //unnamed namespace
struct VM::LocalData {
explicit LocalData (const detail::Callbacks& cb) :
callbacks(cb),
wvm(nullptr)
{}
~LocalData() noexcept {
if (wvm)
wrenFreeVM(wvm);
#if !defined(NDEBUG)
wvm = nullptr;
#endif
}
detail::Callbacks callbacks;
WrenVM* wvm;
};
VM::VM (Configuration* conf, const detail::Callbacks& cb) :
m_callbacks(cb),
m_vm(nullptr)
m_local(std::make_unique<LocalData>(cb))
{
WrenConfiguration wconf;
wrenInitConfiguration(&wconf);
wconf.userData = static_cast<void*>(&m_callbacks);
wconf.userData = static_cast<void*>(&m_local->callbacks);
wconf.initialHeapSize = conf->initial_heap_size();
wconf.minHeapSize = conf->min_heap_size();
@ -72,33 +88,20 @@ namespace wren {
if (cb.load_module_fn)
wconf.loadModuleFn = &load_module_fn;
m_vm = wrenNewVM(&wconf);
if (not m_vm)
m_local->wvm = wrenNewVM(&wconf);
if (not m_local->wvm)
throw std::runtime_error("Failed to initialize Wren VM");
}
VM::VM (VM&& other) :
m_vm(nullptr)
{
std::swap(m_vm, other.m_vm);
m_callbacks = other.m_callbacks;
wrenSetUserData(m_vm, &m_callbacks);
}
VM::~VM() noexcept {
if (m_vm)
wrenFreeVM(m_vm);
#if !defined(NDEBUG)
m_vm = nullptr;
#endif
}
VM::VM (VM&& other) = default;
VM::~VM() noexcept = default;
void VM::interpret (const char* module_name, const char* script) {
using std::string;
using std::runtime_error;
const WrenInterpretResult res = wrenInterpret(m_vm, module_name, script);
const WrenInterpretResult res = wrenInterpret(m_local->wvm, module_name, script);
switch (res) {
case WREN_RESULT_COMPILE_ERROR:
throw runtime_error(string("Compilation of ") + module_name + " has failed");

View file

@ -3,10 +3,7 @@
#include "has_method.hpp"
#include "error_type.hpp"
#include <string>
extern "C" {
typedef struct WrenVM WrenVM;
} //extern C
#include <memory>
namespace wren {
class Configuration;
@ -21,7 +18,7 @@ namespace wren {
char* (*load_module_fn)(Configuration&, VM*, const char*) {nullptr};
Configuration* config_obj {nullptr};
VM* vm {nullptr};
VM* owner {nullptr};
};
} //namespace detail
@ -37,13 +34,14 @@ namespace wren {
void interpret (const std::string& module_name, const std::string& script);
private:
struct LocalData;
VM (Configuration* conf, const detail::Callbacks&);
template <typename T>
detail::Callbacks to_callbacks (T& conf);
detail::Callbacks m_callbacks;
WrenVM* m_vm;
std::unique_ptr<LocalData> m_local;
};
namespace detail {
@ -76,7 +74,7 @@ namespace wren {
detail::Callbacks ret;
ret.config_obj = &conf;
ret.vm = this;
ret.owner = this;
if constexpr (detail::method_write::exists<T>::value)
ret.write_fn = &detail::AnyFunctionWrap<T, decltype(&T::write_fn)>::template call<&T::write_fn>;