Make VM easily movable
This commit is contained in:
parent
ebd455c536
commit
d0be115181
2 changed files with 38 additions and 37 deletions
|
@ -19,39 +19,55 @@ namespace wren {
|
||||||
void write_fn (WrenVM* wvm, const char* text) {
|
void write_fn (WrenVM* wvm, const char* text) {
|
||||||
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
||||||
assert(cb);
|
assert(cb);
|
||||||
assert(cb->write_fn and cb->config_obj and cb->vm);
|
assert(cb->write_fn and cb->config_obj and cb->owner);
|
||||||
cb->write_fn(*cb->config_obj, cb->vm, text);
|
cb->write_fn(*cb->config_obj, cb->owner, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void error_fn (WrenVM* wvm, WrenErrorType type, const char* module, int line, const char* message) {
|
void error_fn (WrenVM* wvm, WrenErrorType type, const char* module, int line, const char* message) {
|
||||||
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
||||||
assert(cb);
|
assert(cb);
|
||||||
assert(cb->error_fn and cb->config_obj and cb->vm);
|
assert(cb->error_fn and cb->config_obj and cb->owner);
|
||||||
cb->error_fn(*cb->config_obj, cb->vm, to_error_type(type), module, line, message);
|
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) {
|
const char* resolve_module_fn (WrenVM* wvm, const char* importer, const char* name) {
|
||||||
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
||||||
assert(cb);
|
assert(cb);
|
||||||
assert(cb->resolve_module_fn and cb->config_obj and cb->vm);
|
assert(cb->resolve_module_fn and cb->config_obj and cb->owner);
|
||||||
return cb->resolve_module_fn(*cb->config_obj, cb->vm, importer, name);
|
return cb->resolve_module_fn(*cb->config_obj, cb->owner, importer, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* load_module_fn (WrenVM* wvm, const char* name) {
|
char* load_module_fn (WrenVM* wvm, const char* name) {
|
||||||
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
|
||||||
assert(cb);
|
assert(cb);
|
||||||
assert(cb->load_module_fn and cb->config_obj and cb->vm);
|
assert(cb->load_module_fn and cb->config_obj and cb->owner);
|
||||||
return cb->load_module_fn(*cb->config_obj, cb->vm, name);
|
return cb->load_module_fn(*cb->config_obj, cb->owner, name);
|
||||||
}
|
}
|
||||||
} //unnamed namespace
|
} //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) :
|
VM::VM (Configuration* conf, const detail::Callbacks& cb) :
|
||||||
m_callbacks(cb),
|
m_local(std::make_unique<LocalData>(cb))
|
||||||
m_vm(nullptr)
|
|
||||||
{
|
{
|
||||||
WrenConfiguration wconf;
|
WrenConfiguration wconf;
|
||||||
wrenInitConfiguration(&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.initialHeapSize = conf->initial_heap_size();
|
||||||
wconf.minHeapSize = conf->min_heap_size();
|
wconf.minHeapSize = conf->min_heap_size();
|
||||||
|
@ -72,33 +88,20 @@ namespace wren {
|
||||||
if (cb.load_module_fn)
|
if (cb.load_module_fn)
|
||||||
wconf.loadModuleFn = &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");
|
throw std::runtime_error("Failed to initialize Wren VM");
|
||||||
}
|
}
|
||||||
|
|
||||||
VM::VM (VM&& other) :
|
VM::VM (VM&& other) = default;
|
||||||
m_vm(nullptr)
|
VM::~VM() noexcept = default;
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
void VM::interpret (const char* module_name, const char* script) {
|
void VM::interpret (const char* module_name, const char* script) {
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::runtime_error;
|
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) {
|
switch (res) {
|
||||||
case WREN_RESULT_COMPILE_ERROR:
|
case WREN_RESULT_COMPILE_ERROR:
|
||||||
throw runtime_error(string("Compilation of ") + module_name + " has failed");
|
throw runtime_error(string("Compilation of ") + module_name + " has failed");
|
||||||
|
|
|
@ -3,10 +3,7 @@
|
||||||
#include "has_method.hpp"
|
#include "has_method.hpp"
|
||||||
#include "error_type.hpp"
|
#include "error_type.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
extern "C" {
|
|
||||||
typedef struct WrenVM WrenVM;
|
|
||||||
} //extern C
|
|
||||||
|
|
||||||
namespace wren {
|
namespace wren {
|
||||||
class Configuration;
|
class Configuration;
|
||||||
|
@ -21,7 +18,7 @@ namespace wren {
|
||||||
char* (*load_module_fn)(Configuration&, VM*, const char*) {nullptr};
|
char* (*load_module_fn)(Configuration&, VM*, const char*) {nullptr};
|
||||||
|
|
||||||
Configuration* config_obj {nullptr};
|
Configuration* config_obj {nullptr};
|
||||||
VM* vm {nullptr};
|
VM* owner {nullptr};
|
||||||
};
|
};
|
||||||
} //namespace detail
|
} //namespace detail
|
||||||
|
|
||||||
|
@ -37,13 +34,14 @@ namespace wren {
|
||||||
void interpret (const std::string& module_name, const std::string& script);
|
void interpret (const std::string& module_name, const std::string& script);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct LocalData;
|
||||||
|
|
||||||
VM (Configuration* conf, const detail::Callbacks&);
|
VM (Configuration* conf, const detail::Callbacks&);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
detail::Callbacks to_callbacks (T& conf);
|
detail::Callbacks to_callbacks (T& conf);
|
||||||
|
|
||||||
detail::Callbacks m_callbacks;
|
std::unique_ptr<LocalData> m_local;
|
||||||
WrenVM* m_vm;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -76,7 +74,7 @@ namespace wren {
|
||||||
|
|
||||||
detail::Callbacks ret;
|
detail::Callbacks ret;
|
||||||
ret.config_obj = &conf;
|
ret.config_obj = &conf;
|
||||||
ret.vm = this;
|
ret.owner = this;
|
||||||
|
|
||||||
if constexpr (detail::method_write::exists<T>::value)
|
if constexpr (detail::method_write::exists<T>::value)
|
||||||
ret.write_fn = &detail::AnyFunctionWrap<T, decltype(&T::write_fn)>::template call<&T::write_fn>;
|
ret.write_fn = &detail::AnyFunctionWrap<T, decltype(&T::write_fn)>::template call<&T::write_fn>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue