lua_State *L = module->lib;
lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t)module->data);
lua_getfield(L, -1, call);
+ lua_remove(L, -2);
lua_pushlightuserdata(L, module);
return L;
}
-/** @internal Helper for calling the entrypoint. */
-static inline int l_ffi_resume(lua_State *L, bool resume, int argc)
-{
- int status = resume ? l_resume(L, argc) : engine_pcall(L, argc);
- switch(status) {
- case LUA_YIELD: /* Continuation */
- return kr_error(EAGAIN);
- case 0: /* Finished */
- return lua_tonumber(L, 1);
- default: /* Error */
- lua_pop(L, 1);
- return kr_error(EIO);
- }
-}
-
/** @internal Continue with coroutine. */
static void l_ffi_resume_cb(uv_idle_t *check)
{
lua_State *L = check->data;
- int status = l_ffi_resume(L, true, 0);
- if (status != kr_error(EAGAIN)) {
+ int status = l_resume(L, 0);
+ if (status != LUA_YIELD) {
uv_idle_stop(check); /* Stop coroutine */
uv_close((uv_handle_t *)check, (uv_close_cb)free);
}
+ lua_pop(L, lua_gettop(L));
}
/** @internal Schedule deferred continuation. */
/** @internal Helper for calling the entrypoint. */
static inline int l_ffi_call(lua_State *L, int argc)
{
- int status = l_ffi_resume(L, false, argc);
- if (status == kr_error(EAGAIN)) {
- return l_ffi_defer(L);
+ int status = lua_pcall(L, argc, LUA_MULTRET, 0);
+ if (status != 0) {
+ lua_pop(L, 1);
+ return kr_error(EIO);
+ }
+
+ int n = lua_gettop(L);
+ if (n > 0) {
+ if (lua_isthread(L, -1)) { /* Continuations */
+ status = l_ffi_defer(lua_tothread(L, -1));
+ } else if (lua_isnumber(L, -1)) { /* Return code */
+ status = lua_tonumber(L, 1);
+ }
+ lua_pop(L, n);
}
return status;
}
static int l_ffi_deinit(struct kr_module *module)
{
lua_State *L = l_ffi_preface(module, "deinit");
- /* @note Do not allow coroutine here. */
- int ret = l_ffi_resume(L, false, 1);
+ int ret = l_ffi_call(L, 1);
/* Free the layer API wrapper */
lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t)module->data);
lua_getfield(L, -1, "_layercdata");
free(lua_touserdata(L, -1));
- lua_pop(L, 1);
+ lua_pop(L, 2);
/* Unref module and unset 'lib', so the module
* interface doesn't attempt to close it.
*/
lua_State *L = module->lib; \
lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t)module->data); \
lua_getfield(L, -1, "layer"); \
+ lua_remove(L, -2); \
lua_getfield(L, -1, (name)); \
+ lua_remove(L, -2); \
if (lua_isnil(L, -1)) { \
+ lua_pop(L, 1); \
return ctx->state; \
} \
lua_pushnumber(L, ctx->state);
LAYER_FFI_CALL(ctx, "begin");
lua_pushlightuserdata(L, module_param);
ctx->data = module_param;
- return l_ffi_resume(L, false, 2);
+ return l_ffi_call(L, 2);
}
static int l_ffi_layer_reset(knot_layer_t *ctx)
{
LAYER_FFI_CALL(ctx, "reset");
lua_pushlightuserdata(L, ctx->data);
- return l_ffi_resume(L, false, 2);
+ return l_ffi_call(L, 2);
}
static int l_ffi_layer_finish(knot_layer_t *ctx)
{
LAYER_FFI_CALL(ctx, "finish");
lua_pushlightuserdata(L, ctx->data);
- return l_ffi_resume(L, false, 2);
+ return l_ffi_call(L, 2);
}
static int l_ffi_layer_consume(knot_layer_t *ctx, knot_pkt_t *pkt)
LAYER_FFI_CALL(ctx, "consume");
lua_pushlightuserdata(L, ctx->data);
lua_pushlightuserdata(L, pkt);
- return l_ffi_resume(L, false, 3);
+ return l_ffi_call(L, 3);
}
static int l_ffi_layer_produce(knot_layer_t *ctx, knot_pkt_t *pkt)
LAYER_FFI_CALL(ctx, "produce");
lua_pushlightuserdata(L, ctx->data);
lua_pushlightuserdata(L, pkt);
- return l_ffi_resume(L, false, 3);
+ return l_ffi_call(L, 3);
}
static int l_ffi_layer_fail(knot_layer_t *ctx, knot_pkt_t *pkt)
LAYER_FFI_CALL(ctx, "fail");
lua_pushlightuserdata(L, ctx->data);
lua_pushlightuserdata(L, pkt);
- return l_ffi_resume(L, false, 3);
+ return l_ffi_call(L, 3);
}
/** @internal Retrieve C layer api wrapper. */
lua_State *L = module->lib;
lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t)module->data);
lua_getfield(L, -1, "_layer_capi");
- if (lua_isnil(L, -1)) {
+ knot_layer_api_t *api = lua_touserdata(L, -1);
+ lua_pop(L, 1);
+ if (!api) {
/* Fabricate layer API wrapping the Lua functions */
knot_layer_api_t *api = malloc(sizeof(*api));
- if (!api) {
- return NULL;
+ if (api) {
+ api->begin = l_ffi_layer_begin;
+ api->finish = l_ffi_layer_finish;
+ api->consume = l_ffi_layer_consume;
+ api->produce = l_ffi_layer_produce;
+ api->reset = l_ffi_layer_reset;
+ api->fail = l_ffi_layer_fail;
+ api->data = module;
}
- api->begin = l_ffi_layer_begin;
- api->finish = l_ffi_layer_finish;
- api->consume = l_ffi_layer_consume;
- api->produce = l_ffi_layer_produce;
- api->reset = l_ffi_layer_reset;
- api->fail = l_ffi_layer_fail;
- api->data = module;
/* Store the api in the registry. */
- lua_pop(L, 1);
lua_pushlightuserdata(L, api);
lua_setfield(L, -2, "_layer_capi");
- return api;
- } else {
- return lua_touserdata(L, -1);
}
+ lua_pop(L, 1); /* Clear module table */
+ return api;
}
#undef LAYER_FFI_CALL
REGISTER_FFI_CALL(L, module->layer, "layer", &l_ffi_layer);
module->data = (void *)(intptr_t)luaL_ref(L, LUA_REGISTRYINDEX);
module->lib = L;
+ lua_pop(L, 1); /* Clear the module global */
return module->init(module);
}