Mercurial > molko
changeset 372:3c378be73844
js: try another approach to shared ownership
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 25 Oct 2021 13:44:49 +0200 |
parents | 8ac282bd5935 |
children | ebaf5490b32f |
files | src/libmlk-core-js/core/js-drawable-stack.c src/libmlk-core-js/core/js-drawable.c src/libmlk-core-js/core/js-drawable.h src/libmlk-core-js/core/js-game.c src/libmlk-core-js/core/js-state.c src/libmlk-core-js/core/js-state.h |
diffstat | 6 files changed, 175 insertions(+), 136 deletions(-) [+] |
line wrap: on
line diff
--- a/src/libmlk-core-js/core/js-drawable-stack.c Mon Oct 25 12:43:09 2021 +0200 +++ b/src/libmlk-core-js/core/js-drawable-stack.c Mon Oct 25 13:44:49 2021 +0200 @@ -76,10 +76,18 @@ DrawableStack_add(duk_context *ctx) { struct drawable_stack *st = self(ctx); - struct drawable *dw = js_drawable_require(ctx, 0); + struct js_drawable *dw = js_drawable_require(ctx, 0); - if (drawable_stack_add(st, dw) < 0) - drawable_finish(dw); + if (drawable_stack_add(st, &dw->dw) < 0) + drawable_finish(&dw->dw); + else { + duk_push_this(ctx); + dw->parent = duk_get_heapptr(ctx, -1); + duk_push_sprintf(ctx, "%p", dw); + duk_dup(ctx, 0); + duk_put_prop(ctx, -3); + duk_pop(ctx); + } return 0; }
--- a/src/libmlk-core-js/core/js-drawable.c Mon Oct 25 12:43:09 2021 +0200 +++ b/src/libmlk-core-js/core/js-drawable.c Mon Oct 25 13:44:49 2021 +0200 @@ -25,51 +25,42 @@ #define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.Drawable") -struct self { - duk_context *ctx; - void *ptr; - struct drawable dw; - unsigned int refc; -}; - -static inline struct self * +static inline struct js_drawable * self(duk_context *ctx) { - struct self *sf = NULL; + struct js_drawable *data = NULL; duk_push_this(ctx); duk_get_prop_string(ctx, -1, SIGNATURE); - sf = duk_to_pointer(ctx, -1); + data = duk_to_pointer(ctx, -1); duk_pop_2(ctx); - if (!sf) + if (!data) return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"), NULL; - return sf; + return data; } -static inline int -callable(struct self *s, const char *prop, duk_context **ctx) +static inline duk_context * +callable(struct js_drawable *data, const char *prop) { - int callable; + duk_context *ctx; - if (!s->ptr) - return 0; + if (!data->ptr) + return NULL; - duk_push_heapptr(s->ctx, s->ptr); - duk_get_prop_string(s->ctx, -1, prop); - duk_remove(s->ctx, -2); + duk_push_heapptr(data->ctx, data->ptr); + duk_get_prop_string(data->ctx, -1, prop); + duk_pull(data->ctx, -2); - if (duk_is_callable(s->ctx, -1)) { - *ctx = s->ctx; - callable = 1; - } else { - *ctx = NULL; - callable = 0; - duk_pop(s->ctx); + if (duk_is_callable(data->ctx, -2)) + ctx = data->ctx; + else { + ctx = NULL; + duk_pop_n(data->ctx, 2); } - return callable; + return ctx; } static int @@ -78,10 +69,11 @@ duk_context *ctx; int ret = 0; - if (callable(dw->data, "update", &ctx)) { + if ((ctx = callable(dw->data, "update"))) { duk_push_uint(ctx, ticks); - duk_call(ctx, 1); + duk_call_method(ctx, 1); ret = duk_to_int(ctx, -1); + duk_pop(ctx); } return ret; @@ -92,8 +84,10 @@ { duk_context *ctx; - if (callable(dw->data, "draw", &ctx)) - duk_call(ctx, 0); + if ((ctx = callable(dw->data, "draw"))) { + duk_call_method(ctx, 0); + duk_pop(ctx); + } } static void @@ -101,17 +95,31 @@ { duk_context *ctx; - if (callable(dw->data, "end", &ctx)) - duk_call(ctx, 0); + if ((ctx = callable(dw->data, "end"))) { + duk_call_method(ctx, 0); + duk_pop(ctx); + } } static void finish(struct drawable *dw) { - struct self *sf = dw->data; + struct js_drawable *data = dw->data; + + /* I must not be called anymore. */ + data->ptr = NULL; - if (!--sf->refc) - free(sf); + /* Remove myself from parent stack if any. */ + if (data->parent) { + duk_push_heapptr(data->ctx, data->parent); + duk_push_sprintf(data->ctx, "%p", data); + duk_del_prop(data->ctx, -2); + duk_pop(data->ctx); + data->parent = NULL; + } + + if (--data->refc == 0) + free(data); } static duk_ret_t @@ -149,23 +157,23 @@ static duk_ret_t Drawable_constructor(duk_context *ctx) { - struct self *self; + struct js_drawable *data; const int x = duk_require_int(ctx, 0); const int y = duk_require_int(ctx, 1); - self = alloc_new0(sizeof (*self)); - self->refc = 1; - self->ctx = ctx; - self->dw.x = x; - self->dw.y = y; - self->dw.data = self; - self->dw.update = update; - self->dw.finish = finish; - self->dw.draw = draw; - self->dw.end = end; + data = alloc_new0(sizeof (*data)); + data->refc = 1; + data->ctx = ctx; + data->dw.x = x; + data->dw.y = y; + data->dw.data = self; + data->dw.update = update; + data->dw.finish = finish; + data->dw.draw = draw; + data->dw.end = end; duk_push_this(ctx); - self->ptr = duk_get_heapptr(ctx, -1); + data->ptr = duk_get_heapptr(ctx, -1); duk_push_pointer(ctx, self); duk_put_prop_string(ctx, -2, SIGNATURE); duk_push_string(ctx, "x"); @@ -184,14 +192,12 @@ static duk_ret_t Drawable_destructor(duk_context *ctx) { - struct self *sf; + struct js_drawable *data; duk_get_prop_string(ctx, 0, SIGNATURE); - if ((sf = duk_to_pointer(ctx, -1))) { - sf->ptr = NULL; - drawable_finish(&sf->dw); - } + if ((data = duk_to_pointer(ctx, -1))) + drawable_finish(&data->dw); duk_del_prop_string(ctx, 0, SIGNATURE); duk_pop(ctx); @@ -199,7 +205,6 @@ return 0; } - void js_drawable_bind(duk_context *ctx) { @@ -213,21 +218,21 @@ duk_put_global_string(ctx, "Drawable"); } -struct drawable * +struct js_drawable * js_drawable_require(duk_context *ctx, duk_idx_t idx) { - struct self *sf = NULL; + struct js_drawable *data = NULL; if (duk_is_object(ctx, idx)) { duk_get_prop_string(ctx, idx, SIGNATURE); - sf = duk_to_pointer(ctx, -1); + data = duk_to_pointer(ctx, -1); duk_pop(ctx); } - if (!sf) + if (!data) return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"), NULL; - sf->refc++; + data->refc++; - return &sf->dw; + return data; }
--- a/src/libmlk-core-js/core/js-drawable.h Mon Oct 25 12:43:09 2021 +0200 +++ b/src/libmlk-core-js/core/js-drawable.h Mon Oct 25 13:44:49 2021 +0200 @@ -21,12 +21,20 @@ #include <duktape.h> -struct drawable; +#include <core/drawable.h> + +struct js_drawable { + duk_context *ctx; + void *ptr; + void *parent; + unsigned int refc; + struct drawable dw; +}; void js_drawable_bind(duk_context *); -struct drawable * +struct js_drawable * js_drawable_require(duk_context *, duk_idx_t); #endif /* !MLK_CORE_JS_DRAWABLE_H */
--- a/src/libmlk-core-js/core/js-game.c Mon Oct 25 12:43:09 2021 +0200 +++ b/src/libmlk-core-js/core/js-game.c Mon Oct 25 13:44:49 2021 +0200 @@ -31,14 +31,21 @@ static duk_ret_t Game_push(duk_context *ctx) { - struct state *state = js_state_require(ctx, 0); + struct js_state *state = js_state_require(ctx, 0); if (game.state == &game.states[GAME_STATE_MAX]) { - state_finish(state); + state_finish(&state->st); return duk_error(ctx, DUK_ERR_RANGE_ERROR, "too many states"); } - game_push(state); + duk_push_this(ctx); + state->parent = duk_get_heapptr(ctx, -1); + duk_push_sprintf(ctx, "%p", state); + duk_dup(ctx, 0); + duk_put_prop(ctx, -3); + duk_pop(ctx); + + game_push(&state->st); return 0; }
--- a/src/libmlk-core-js/core/js-state.c Mon Oct 25 12:43:09 2021 +0200 +++ b/src/libmlk-core-js/core/js-state.c Mon Oct 25 13:44:49 2021 +0200 @@ -27,35 +27,26 @@ #define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.State") -struct self { +static inline duk_context * +callable(struct js_state *data, const char *prop) +{ duk_context *ctx; - void *ptr; - struct state state; - unsigned int refc; -}; -static inline int -callable(struct self *s, const char *prop, duk_context **ctx) -{ - int callable; + if (!data->ptr) + return NULL; - if (!s->ptr) - return 0; - - duk_push_heapptr(s->ctx, s->ptr); - duk_get_prop_string(s->ctx, -1, prop); - duk_remove(s->ctx, -2); + duk_push_heapptr(data->ctx, data->ptr); + duk_get_prop_string(data->ctx, -1, prop); + duk_pull(data->ctx, -2); - if (duk_is_callable(s->ctx, -1)) { - *ctx = s->ctx; - callable = 1; - } else { - *ctx = NULL; - callable = 0; - duk_pop(s->ctx); + if (duk_is_callable(data->ctx, -2)) + ctx = data->ctx; + else { + ctx = NULL; + duk_pop_n(data->ctx, 2); } - return callable; + return ctx; } static void @@ -63,8 +54,8 @@ { duk_context *ctx; - if (callable(state->data, "start", &ctx)) { - duk_call(ctx, 0); + if ((ctx = callable(state->data, "start"))) { + duk_call_method(ctx, 0); duk_pop(ctx); } } @@ -74,9 +65,9 @@ { duk_context *ctx; - if (callable(state->data, "handle", &ctx)) { + if ((ctx = callable(state->data, "handle"))) { js_event_push(ctx, ev); - duk_call(ctx, 1); + duk_call_method(ctx, 1); duk_pop(ctx); } } @@ -86,9 +77,9 @@ { duk_context *ctx; - if (callable(state->data, "update", &ctx)) { + if ((ctx = callable(state->data, "update"))) { duk_push_uint(ctx, ticks); - duk_call(ctx, 1); + duk_call_method(ctx, 1); duk_pop(ctx); } } @@ -98,8 +89,8 @@ { duk_context *ctx; - if (callable(state->data, "draw", &ctx)) { - duk_call(ctx, 0); + if ((ctx = callable(state->data, "draw"))) { + duk_call_method(ctx, 0); duk_pop(ctx); } } @@ -109,8 +100,8 @@ { duk_context *ctx; - if (callable(state->data, "suspend", &ctx)) { - duk_call(ctx, 0); + if ((ctx = callable(state->data, "suspend"))) { + duk_call_method(ctx, 0); duk_pop(ctx); } } @@ -120,8 +111,8 @@ { duk_context *ctx; - if (callable(state->data, "resume", &ctx)) { - duk_call(ctx, 0); + if ((ctx = callable(state->data, "resume"))) { + duk_call_method(ctx, 0); duk_pop(ctx); } } @@ -131,8 +122,8 @@ { duk_context *ctx; - if (callable(state->data, "end", &ctx)) { - duk_call(ctx, 0); + if ((ctx = callable(state->data, "end"))) { + duk_call_method(ctx, 0); duk_pop(ctx); } } @@ -140,33 +131,45 @@ static void finish(struct state *state) { - struct self *self = state->data; + struct js_state *data = state->data; + + /* I must not be called anymore. */ + data->ptr = NULL; - if (!--self->refc) - free(self); + /* Remove myself from parent stack if any. */ + if (data->parent) { + duk_push_heapptr(data->ctx, data->parent); + duk_push_sprintf(data->ctx, "%p", data); + duk_del_prop(data->ctx, -2); + duk_pop(data->ctx); + data->parent = NULL; + } + + if (--data->refc == 0) + free(data); } static duk_ret_t State_constructor(duk_context *ctx) { - struct self *self; + struct js_state *data; - self = alloc_new0(sizeof (*self)); - self->ctx = ctx; - self->refc = 1; - self->state.data = self; - self->state.start = start; - self->state.handle = handle; - self->state.update = update; - self->state.draw = draw; - self->state.suspend = suspend; - self->state.resume = resume; - self->state.end = end; - self->state.finish = finish; + data = alloc_new0(sizeof (*data)); + data->ctx = ctx; + data->refc = 1; + data->st.data = data; + data->st.start = start; + data->st.handle = handle; + data->st.update = update; + data->st.draw = draw; + data->st.suspend = suspend; + data->st.resume = resume; + data->st.end = end; + data->st.finish = finish; duk_push_this(ctx); - self->ptr = duk_get_heapptr(ctx, -1); - duk_push_pointer(ctx, self); + data->ptr = duk_get_heapptr(ctx, -1); + duk_push_pointer(ctx, data); duk_put_prop_string(ctx, -2, SIGNATURE); duk_pop(ctx); @@ -176,14 +179,12 @@ static duk_ret_t State_destructor(duk_context *ctx) { - struct self *self; + struct js_state *data; duk_get_prop_string(ctx, 0, SIGNATURE); - if ((self = duk_to_pointer(ctx, -1))) { - self->ptr = NULL; - state_finish(&self->state); - } + if ((data = duk_to_pointer(ctx, -1))) + state_finish(&data->st); duk_pop(ctx); @@ -203,21 +204,21 @@ duk_put_global_string(ctx, "State"); } -struct state * +struct js_state * js_state_require(duk_context *ctx, duk_idx_t idx) { - struct self *self = NULL; + struct js_state *data = NULL; if (duk_is_object(ctx, idx)) { duk_get_prop_string(ctx, idx, SIGNATURE); - self = duk_to_pointer(ctx, -1); + data = duk_to_pointer(ctx, -1); duk_pop(ctx); } - if (!self) + if (!data) return (void)duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a State object"), NULL; - self->refc++; + data->refc++; - return &self->state; + return data; }
--- a/src/libmlk-core-js/core/js-state.h Mon Oct 25 12:43:09 2021 +0200 +++ b/src/libmlk-core-js/core/js-state.h Mon Oct 25 13:44:49 2021 +0200 @@ -21,10 +21,20 @@ #include <duktape.h> +#include <core/state.h> + +struct js_state { + duk_context *ctx; + void *ptr; + void *parent; + unsigned int refc; + struct state st; +}; + void js_state_bind(duk_context *); -struct state * +struct js_state * js_state_require(duk_context *, duk_idx_t); #endif /* !MLK_CORE_JS_STATE_H */