initial support for "threads"

master
Daniel Kolesa 2018-04-26 19:23:11 +02:00
parent bd008ffb46
commit fb78b4acdd
2 changed files with 90 additions and 39 deletions

View File

@ -352,6 +352,32 @@ struct OSTD_EXPORT cs_state {
cs_state(cs_alloc_cb func = cs_default_alloc, void *data = nullptr);
virtual ~cs_state();
cs_state(cs_state const &) = delete;
cs_state(cs_state &&s) {
swap(s);
}
cs_state &operator=(cs_state const &) = delete;
cs_state &operator=(cs_state &&s) {
swap(s);
s.destroy();
return *this;
}
void destroy();
void swap(cs_state &s) {
std::swap(p_state, s.p_state);
std::swap(p_callstack, s.p_callstack);
std::swap(identflags, s.identflags);
std::swap(p_pstate, s.p_pstate);
std::swap(p_inloop, s.p_inloop);
std::swap(p_owner, s.p_owner);
std::swap(p_callhook, s.p_callhook);
}
cs_state new_thread();
cs_hook_cb set_call_hook(cs_hook_cb func);
cs_hook_cb const &get_call_hook() const;
cs_hook_cb &get_call_hook();
@ -463,12 +489,15 @@ struct OSTD_EXPORT cs_state {
virtual void print_var(cs_var *v);
private:
OSTD_LOCAL cs_state(cs_shared_state *s);
cs_ident *add_ident(cs_ident *id);
void *alloc(void *ptr, size_t olds, size_t news);
OSTD_LOCAL void *alloc(void *ptr, size_t olds, size_t news);
cs_gen_state *p_pstate = nullptr;
int p_inloop = 0;
bool p_owner = false;
char p_errbuf[512];

View File

@ -311,6 +311,7 @@ cs_state::cs_state(cs_alloc_cb func, void *data):
func(data, nullptr, 0, sizeof(cs_shared_state))
);
new (p_state) cs_shared_state();
p_owner = true;
/* set up allocator, from now we can call into alloc() */
p_state->allocf = func;
p_state->aptr = data;
@ -414,8 +415,12 @@ cs_state::cs_state(cs_alloc_cb func, void *data):
cs_init_lib_base(*this);
}
cs_state::~cs_state() {
if (!p_state) {
OSTD_EXPORT cs_state::~cs_state() {
destroy();
}
OSTD_EXPORT void cs_state::destroy() {
if (!p_state || !p_owner) {
return;
}
for (auto &p: p_state->idents) {
@ -430,17 +435,25 @@ cs_state::~cs_state() {
p_state->destroy(p_state);
}
cs_hook_cb cs_state::set_call_hook(cs_hook_cb func) {
cs_state::cs_state(cs_shared_state *s):
p_state(s), p_owner(false)
{}
OSTD_EXPORT cs_state cs_state::new_thread() {
return cs_state{p_state};
}
OSTD_EXPORT cs_hook_cb cs_state::set_call_hook(cs_hook_cb func) {
auto hk = std::move(p_callhook);
p_callhook = std::move(func);
return hk;
}
cs_hook_cb const &cs_state::get_call_hook() const {
OSTD_EXPORT cs_hook_cb const &cs_state::get_call_hook() const {
return p_callhook;
}
cs_hook_cb &cs_state::get_call_hook() {
OSTD_EXPORT cs_hook_cb &cs_state::get_call_hook() {
return p_callhook;
}
@ -448,7 +461,7 @@ void *cs_state::alloc(void *ptr, size_t os, size_t ns) {
return p_state->alloc(ptr, os, ns);
}
void cs_state::clear_override(cs_ident &id) {
OSTD_EXPORT void cs_state::clear_override(cs_ident &id) {
if (!(id.get_flags() & CS_IDF_OVERRIDDEN)) {
return;
}
@ -483,13 +496,13 @@ void cs_state::clear_override(cs_ident &id) {
id.p_flags &= ~CS_IDF_OVERRIDDEN;
}
void cs_state::clear_overrides() {
OSTD_EXPORT void cs_state::clear_overrides() {
for (auto &p: p_state->idents) {
clear_override(*(p.second));
}
}
cs_ident *cs_state::add_ident(cs_ident *id) {
OSTD_EXPORT cs_ident *cs_state::add_ident(cs_ident *id) {
if (!id) {
return nullptr;
}
@ -499,7 +512,7 @@ cs_ident *cs_state::add_ident(cs_ident *id) {
return p_state->identmap.back();
}
cs_ident *cs_state::new_ident(ostd::string_range name, int flags) {
OSTD_EXPORT cs_ident *cs_state::new_ident(ostd::string_range name, int flags) {
cs_ident *id = get_ident(name);
if (!id) {
if (cs_check_num(name)) {
@ -512,7 +525,7 @@ cs_ident *cs_state::new_ident(ostd::string_range name, int flags) {
return id;
}
cs_ident *cs_state::force_ident(cs_value &v) {
OSTD_EXPORT cs_ident *cs_state::force_ident(cs_value &v) {
switch (v.get_type()) {
case cs_value_type::Ident:
return v.get_ident();
@ -530,7 +543,7 @@ cs_ident *cs_state::force_ident(cs_value &v) {
return p_state->identmap[DummyIdx];
}
cs_ident *cs_state::get_ident(ostd::string_range name) {
OSTD_EXPORT cs_ident *cs_state::get_ident(ostd::string_range name) {
auto id = p_state->idents.find(name);
if (id != p_state->idents.end()) {
return id->second;
@ -538,7 +551,7 @@ cs_ident *cs_state::get_ident(ostd::string_range name) {
return nullptr;
}
cs_alias *cs_state::get_alias(ostd::string_range name) {
OSTD_EXPORT cs_alias *cs_state::get_alias(ostd::string_range name) {
auto id = get_ident(name);
if (!id || !id->is_alias()) {
return nullptr;
@ -546,23 +559,23 @@ cs_alias *cs_state::get_alias(ostd::string_range name) {
return static_cast<cs_alias *>(id);
}
bool cs_state::have_ident(ostd::string_range name) {
OSTD_EXPORT bool cs_state::have_ident(ostd::string_range name) {
return p_state->idents.find(name) != p_state->idents.end();
}
cs_ident_r cs_state::get_idents() {
OSTD_EXPORT cs_ident_r cs_state::get_idents() {
return cs_ident_r(
p_state->identmap.data(),
p_state->identmap.data() + p_state->identmap.size()
);
}
cs_const_ident_r cs_state::get_idents() const {
OSTD_EXPORT cs_const_ident_r cs_state::get_idents() const {
auto ptr = const_cast<cs_ident const **>(p_state->identmap.data());
return cs_const_ident_r(ptr, ptr + p_state->identmap.size());
}
cs_ivar *cs_state::new_ivar(
OSTD_EXPORT cs_ivar *cs_state::new_ivar(
ostd::string_range n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags
) {
return add_ident(
@ -570,7 +583,7 @@ cs_ivar *cs_state::new_ivar(
)->get_ivar();
}
cs_fvar *cs_state::new_fvar(
OSTD_EXPORT cs_fvar *cs_state::new_fvar(
ostd::string_range n, cs_float m, cs_float x, cs_float v, cs_var_cb f, int flags
) {
return add_ident(
@ -578,7 +591,7 @@ cs_fvar *cs_state::new_fvar(
)->get_fvar();
}
cs_svar *cs_state::new_svar(
OSTD_EXPORT cs_svar *cs_state::new_svar(
ostd::string_range n, cs_string v, cs_var_cb f, int flags
) {
return add_ident(
@ -586,7 +599,7 @@ cs_svar *cs_state::new_svar(
)->get_svar();
}
void cs_state::reset_var(ostd::string_range name) {
OSTD_EXPORT void cs_state::reset_var(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id) {
throw cs_error(*this, "variable %s does not exist", name);
@ -597,14 +610,14 @@ void cs_state::reset_var(ostd::string_range name) {
clear_override(*id);
}
void cs_state::touch_var(ostd::string_range name) {
OSTD_EXPORT void cs_state::touch_var(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (id && id->is_var()) {
static_cast<cs_var *>(id)->changed(*this);
}
}
void cs_state::set_alias(ostd::string_range name, cs_value v) {
OSTD_EXPORT void cs_state::set_alias(ostd::string_range name, cs_value v) {
cs_ident *id = get_ident(name);
if (id) {
switch (id->get_type()) {
@ -639,7 +652,7 @@ void cs_state::set_alias(ostd::string_range name, cs_value v) {
}
}
void cs_state::print_var(cs_var *v) {
OSTD_EXPORT void cs_state::print_var(cs_var *v) {
ostd::writeln(v->to_printable());
}
@ -723,7 +736,7 @@ static inline void cs_override_var(cs_state &cs, cs_var *v, int &vflags, SF sf)
}
}
void cs_state::set_var_int(
OSTD_EXPORT void cs_state::set_var_int(
ostd::string_range name, cs_int v, bool dofunc, bool doclamp
) {
cs_ident *id = get_ident(name);
@ -745,7 +758,7 @@ void cs_state::set_var_int(
}
}
void cs_state::set_var_float(
OSTD_EXPORT void cs_state::set_var_float(
ostd::string_range name, cs_float v, bool dofunc, bool doclamp
) {
cs_ident *id = get_ident(name);
@ -767,7 +780,7 @@ void cs_state::set_var_float(
}
}
void cs_state::set_var_str(
OSTD_EXPORT void cs_state::set_var_str(
ostd::string_range name, ostd::string_range v, bool dofunc
) {
cs_ident *id = get_ident(name);
@ -785,7 +798,8 @@ void cs_state::set_var_str(
}
}
std::optional<cs_int> cs_state::get_var_int(ostd::string_range name) {
OSTD_EXPORT std::optional<cs_int>
cs_state::get_var_int(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id || id->is_ivar()) {
return std::nullopt;
@ -793,7 +807,8 @@ std::optional<cs_int> cs_state::get_var_int(ostd::string_range name) {
return static_cast<cs_ivar *>(id)->get_value();
}
std::optional<cs_float> cs_state::get_var_float(ostd::string_range name) {
OSTD_EXPORT std::optional<cs_float>
cs_state::get_var_float(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id || id->is_fvar()) {
return std::nullopt;
@ -801,7 +816,8 @@ std::optional<cs_float> cs_state::get_var_float(ostd::string_range name) {
return static_cast<cs_fvar *>(id)->get_value();
}
std::optional<cs_string> cs_state::get_var_str(ostd::string_range name) {
OSTD_EXPORT std::optional<cs_string>
cs_state::get_var_str(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id || id->is_svar()) {
return std::nullopt;
@ -809,7 +825,8 @@ std::optional<cs_string> cs_state::get_var_str(ostd::string_range name) {
return cs_string(static_cast<cs_svar *>(id)->get_value());
}
std::optional<cs_int> cs_state::get_var_min_int(ostd::string_range name) {
OSTD_EXPORT std::optional<cs_int>
cs_state::get_var_min_int(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id || id->is_ivar()) {
return std::nullopt;
@ -817,7 +834,8 @@ std::optional<cs_int> cs_state::get_var_min_int(ostd::string_range name) {
return static_cast<cs_ivar *>(id)->get_val_min();
}
std::optional<cs_int> cs_state::get_var_max_int(ostd::string_range name) {
OSTD_EXPORT std::optional<cs_int>
cs_state::get_var_max_int(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id || id->is_ivar()) {
return std::nullopt;
@ -825,7 +843,8 @@ std::optional<cs_int> cs_state::get_var_max_int(ostd::string_range name) {
return static_cast<cs_ivar *>(id)->get_val_max();
}
std::optional<cs_float> cs_state::get_var_min_float(ostd::string_range name) {
OSTD_EXPORT std::optional<cs_float>
cs_state::get_var_min_float(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id || id->is_fvar()) {
return std::nullopt;
@ -833,7 +852,8 @@ std::optional<cs_float> cs_state::get_var_min_float(ostd::string_range name) {
return static_cast<cs_fvar *>(id)->get_val_min();
}
std::optional<cs_float> cs_state::get_var_max_float(ostd::string_range name) {
OSTD_EXPORT std::optional<cs_float>
cs_state::get_var_max_float(ostd::string_range name) {
cs_ident *id = get_ident(name);
if (!id || id->is_fvar()) {
return std::nullopt;
@ -841,7 +861,7 @@ std::optional<cs_float> cs_state::get_var_max_float(ostd::string_range name) {
return static_cast<cs_fvar *>(id)->get_val_max();
}
std::optional<cs_string>
OSTD_EXPORT std::optional<cs_string>
cs_state::get_alias_val(ostd::string_range name) {
cs_alias *a = get_alias(name);
if (!a) {
@ -874,7 +894,7 @@ cs_int cs_clamp_var(cs_state &cs, cs_ivar *iv, cs_int v) {
);
}
void cs_state::set_var_int_checked(cs_ivar *iv, cs_int v) {
OSTD_EXPORT void cs_state::set_var_int_checked(cs_ivar *iv, cs_int v) {
if (iv->get_flags() & CS_IDF_READONLY) {
throw cs_error(
*this, "variable '%s' is read only", iv->get_name()
@ -891,7 +911,7 @@ void cs_state::set_var_int_checked(cs_ivar *iv, cs_int v) {
iv->changed(*this);
}
void cs_state::set_var_int_checked(cs_ivar *iv, cs_value_r args) {
OSTD_EXPORT void cs_state::set_var_int_checked(cs_ivar *iv, cs_value_r args) {
cs_int v = args[0].force_int();
if ((iv->get_flags() & CS_IDF_HEX) && (args.size() > 1)) {
v = (v << 16) | (args[1].force_int() << 8);
@ -917,7 +937,7 @@ cs_float cs_clamp_fvar(cs_state &cs, cs_fvar *fv, cs_float v) {
return v;
}
void cs_state::set_var_float_checked(cs_fvar *fv, cs_float v) {
OSTD_EXPORT void cs_state::set_var_float_checked(cs_fvar *fv, cs_float v) {
if (fv->get_flags() & CS_IDF_READONLY) {
throw cs_error(
*this, "variable '%s' is read only", fv->get_name()
@ -934,7 +954,9 @@ void cs_state::set_var_float_checked(cs_fvar *fv, cs_float v) {
fv->changed(*this);
}
void cs_state::set_var_str_checked(cs_svar *sv, ostd::string_range v) {
OSTD_EXPORT void cs_state::set_var_str_checked(
cs_svar *sv, ostd::string_range v
) {
if (sv->get_flags() & CS_IDF_READONLY) {
throw cs_error(
*this, "variable '%s' is read only", sv->get_name()
@ -948,7 +970,7 @@ void cs_state::set_var_str_checked(cs_svar *sv, ostd::string_range v) {
sv->changed(*this);
}
cs_command *cs_state::new_command(
OSTD_EXPORT cs_command *cs_state::new_command(
ostd::string_range name, ostd::string_range args, cs_command_cb func
) {
int nargs = 0;