event-dispatcher: refactor to use before/after dependencies on hooks
* Remove entirely the hook priority numbers and use before/after dependencies * Split the WpEvent code out of WpEventDispatcher * Add methods on WpEvent to interface with it from the WpEventDispatcher. As a bonus, we can now also implement tooling to inspect which hooks would in theory run for an event and write tests around that * Removed some internal debugging facilities and log calls, will redo it later. * Using spa_list now for the list of hooks, to reduce the number of allocations happening in the "hook collection" algorithm * Switched some internal data to use g_new0 instead of g_slice_new0 * Added g_free to free WpEvent structures... surprisingly, we were leaking them before
This commit is contained in:

committed by
Julian Bouzas

parent
5a435fae11
commit
3a23fb451a
@@ -1916,40 +1916,105 @@ static int
|
||||
simple_event_hook_new (lua_State *L)
|
||||
{
|
||||
WpEventHook *hook = NULL;
|
||||
gint priority = 0;
|
||||
gint priority_type = 0;
|
||||
int before_size = 0, after_size = 0, i = 0;
|
||||
const gchar **before, **after;
|
||||
const gchar *name;
|
||||
GClosure *closure = NULL;
|
||||
|
||||
/* discard any possible arguments after the first one to avoid
|
||||
any surprises when working with absolute stack indices below */
|
||||
lua_settop (L, 1);
|
||||
|
||||
/* validate arguments */
|
||||
luaL_checktype (L, 1, LUA_TTABLE);
|
||||
|
||||
lua_pushliteral (L, "name");
|
||||
if (lua_gettable (L, 1) != LUA_TSTRING)
|
||||
if (lua_getfield (L, 1, "name") != LUA_TSTRING)
|
||||
luaL_error(L, "SimpleEventHook: expected 'name' as string");
|
||||
name = lua_tostring (L, -1);
|
||||
lua_pop (L, 1);
|
||||
|
||||
lua_pushliteral (L, "priority");
|
||||
priority_type = lua_gettable (L, 1);
|
||||
if (priority_type == LUA_TNUMBER)
|
||||
priority = lua_tointeger (L, -1);
|
||||
else
|
||||
luaL_error (L, "SimpleEventHook: expected 'priority' as number");
|
||||
lua_pop (L, 1);
|
||||
|
||||
lua_pushliteral (L, "execute");
|
||||
if (lua_gettable (L, 1) == LUA_TFUNCTION)
|
||||
closure = wplua_function_to_closure (L, -1);
|
||||
else
|
||||
if (lua_getfield (L, 1, "execute") != LUA_TFUNCTION)
|
||||
luaL_error (L, "SimpleEventHook: expected 'execute' as function");
|
||||
lua_pop (L, 1);
|
||||
|
||||
hook = wp_simple_event_hook_new (name, priority, closure);
|
||||
switch (lua_getfield (L, 1, "before")) {
|
||||
case LUA_TTABLE:
|
||||
lua_len (L, -1);
|
||||
before_size = lua_tointeger (L, -1);
|
||||
lua_pop (L, 1);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
before_size = 1;
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
before_size = 0;
|
||||
break;
|
||||
default:
|
||||
luaL_error(L, "SimpleEventHook: unexpected value type for 'before'; "
|
||||
"should be table or string");
|
||||
}
|
||||
|
||||
switch (lua_getfield (L, 1, "after")) {
|
||||
case LUA_TTABLE:
|
||||
lua_len (L, -1);
|
||||
after_size = lua_tointeger (L, -1);
|
||||
lua_pop (L, 1);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
after_size = 1;
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
after_size = 0;
|
||||
break;
|
||||
default:
|
||||
luaL_error(L, "SimpleEventHook: unexpected value type for 'after'; "
|
||||
"should be table or string");
|
||||
}
|
||||
|
||||
/* allocate C stack space for before & after arrays */
|
||||
before = before_size > 0 ?
|
||||
(const gchar **) g_newa (gpointer, before_size + 1) : NULL;
|
||||
after = after_size > 0 ?
|
||||
(const gchar **) g_newa (gpointer, after_size + 1) : NULL;
|
||||
|
||||
/* parse before */
|
||||
if (lua_type (L, 4) == LUA_TTABLE && before_size > 0) {
|
||||
i = 0;
|
||||
lua_pushnil (L);
|
||||
while (lua_next (L, 4) && i < before_size) {
|
||||
before[i++] = luaL_checkstring (L, -1);
|
||||
/* bring the key on top without popping the string value */
|
||||
lua_rotate (L, lua_gettop (L) - 1, 1);
|
||||
}
|
||||
before[i] = NULL;
|
||||
} else if (lua_type (L, 4) == LUA_TSTRING) {
|
||||
before[0] = lua_tostring (L, 4);
|
||||
before[1] = NULL;
|
||||
}
|
||||
|
||||
/* parse after */
|
||||
if (lua_type (L, 5) == LUA_TTABLE && after_size > 0) {
|
||||
i = 0;
|
||||
lua_pushnil (L);
|
||||
while (lua_next (L, 5) && i < after_size - 1) {
|
||||
after[i++] = luaL_checkstring (L, -1);
|
||||
/* bring the key on top without popping the string value */
|
||||
lua_rotate (L, lua_gettop (L) - 1, 1);
|
||||
}
|
||||
after[i] = NULL;
|
||||
} else if (lua_type (L, 5) == LUA_TSTRING) {
|
||||
after[0] = lua_tostring (L, 5);
|
||||
after[1] = NULL;
|
||||
}
|
||||
|
||||
name = lua_tostring (L, 2);
|
||||
closure = wplua_function_to_closure (L, 3);
|
||||
|
||||
hook = wp_simple_event_hook_new (name, before, after, closure);
|
||||
|
||||
/* clear the lua stack now to make some space */
|
||||
lua_settop (L, 1);
|
||||
|
||||
wplua_pushobject (L, hook);
|
||||
|
||||
lua_pushliteral (L, "interests");
|
||||
if (lua_gettable (L, 1) == LUA_TTABLE) {
|
||||
if (lua_getfield (L, 1, "interests") == LUA_TTABLE) {
|
||||
lua_pushnil (L);
|
||||
while (lua_next (L, -2)) {
|
||||
WpObjectInterest *interest =
|
||||
@@ -2090,49 +2155,117 @@ static int
|
||||
async_event_hook_new (lua_State *L)
|
||||
{
|
||||
WpEventHook *hook = NULL;
|
||||
int before_size = 0, after_size = 0, i = 0;
|
||||
const gchar **before, **after;
|
||||
const gchar *name;
|
||||
gint priority = 0;
|
||||
gint priority_type = 0;
|
||||
GClosure *get_next_step = NULL;
|
||||
GClosure *execute_step = NULL;
|
||||
|
||||
/* discard any possible arguments after the first one to avoid
|
||||
any surprises when working with absolute stack indices below */
|
||||
lua_settop (L, 1);
|
||||
|
||||
/* validate arguments */
|
||||
luaL_checktype (L, 1, LUA_TTABLE);
|
||||
|
||||
lua_pushliteral (L, "name");
|
||||
if (lua_gettable (L, 1) != LUA_TSTRING)
|
||||
luaL_error (L, "AsyncEventHook: expected 'name' as string");
|
||||
name = lua_tostring (L, -1);
|
||||
lua_pop (L, 1);
|
||||
if (lua_getfield (L, 1, "name") != LUA_TSTRING)
|
||||
luaL_error(L, "AsyncEventHook: expected 'name' as string");
|
||||
|
||||
lua_pushliteral (L, "priority");
|
||||
priority_type = lua_gettable(L, 1);
|
||||
if (priority_type == LUA_TNUMBER)
|
||||
priority = lua_tointeger (L, -1);
|
||||
else
|
||||
luaL_error(L, "AsyncEventHook: expected 'priority' as number");
|
||||
lua_pop (L, 1);
|
||||
|
||||
lua_pushliteral (L, "steps");
|
||||
if (lua_gettable (L, 1) != LUA_TTABLE)
|
||||
if (lua_getfield (L, 1, "steps") != LUA_TTABLE)
|
||||
luaL_error (L, "AsyncEventHook: expected 'steps' as table");
|
||||
|
||||
async_event_hook_prepare_steps_table (L, -1);
|
||||
switch (lua_getfield (L, 1, "before")) {
|
||||
case LUA_TTABLE:
|
||||
lua_len (L, -1);
|
||||
before_size = lua_tointeger (L, -1);
|
||||
lua_pop (L, 1);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
before_size = 1;
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
before_size = 0;
|
||||
break;
|
||||
default:
|
||||
luaL_error(L, "AsyncEventHook: unexpected value type for 'before'; "
|
||||
"should be table or string");
|
||||
}
|
||||
|
||||
lua_pushvalue (L, -1);
|
||||
switch (lua_getfield (L, 1, "after")) {
|
||||
case LUA_TTABLE:
|
||||
lua_len (L, -1);
|
||||
after_size = lua_tointeger (L, -1);
|
||||
lua_pop (L, 1);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
after_size = 1;
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
after_size = 0;
|
||||
break;
|
||||
default:
|
||||
luaL_error(L, "AsyncEventHook: unexpected value type for 'after'; "
|
||||
"should be table or string");
|
||||
}
|
||||
|
||||
/* allocate C stack space for before & after arrays */
|
||||
before = before_size > 0 ?
|
||||
(const gchar **) g_newa (gpointer, before_size + 1) : NULL;
|
||||
after = after_size > 0 ?
|
||||
(const gchar **) g_newa (gpointer, after_size + 1) : NULL;
|
||||
|
||||
/* parse before */
|
||||
if (lua_type (L, 4) == LUA_TTABLE && before_size > 0) {
|
||||
i = 0;
|
||||
lua_pushnil (L);
|
||||
while (lua_next (L, 4) && i < before_size) {
|
||||
before[i++] = luaL_checkstring (L, -1);
|
||||
/* bring the key on top without popping the string value */
|
||||
lua_rotate (L, lua_gettop (L) - 1, 1);
|
||||
}
|
||||
before[i] = NULL;
|
||||
} else if (lua_type (L, 4) == LUA_TSTRING) {
|
||||
before[0] = lua_tostring (L, 4);
|
||||
before[1] = NULL;
|
||||
}
|
||||
|
||||
/* parse after */
|
||||
if (lua_type (L, 5) == LUA_TTABLE && after_size > 0) {
|
||||
i = 0;
|
||||
lua_pushnil (L);
|
||||
while (lua_next (L, 5) && i < after_size - 1) {
|
||||
after[i++] = luaL_checkstring (L, -1);
|
||||
/* bring the key on top without popping the string value */
|
||||
lua_rotate (L, lua_gettop (L) - 1, 1);
|
||||
}
|
||||
after[i] = NULL;
|
||||
} else if (lua_type (L, 5) == LUA_TSTRING) {
|
||||
after[0] = lua_tostring (L, 5);
|
||||
after[1] = NULL;
|
||||
}
|
||||
|
||||
name = lua_tostring (L, 2);
|
||||
async_event_hook_prepare_steps_table (L, 3);
|
||||
|
||||
lua_pushvalue (L, 3); /* pass 'steps' table as upvalue */
|
||||
lua_pushcclosure (L, async_event_hook_get_next_step, 1);
|
||||
get_next_step = wplua_function_to_closure (L, -1);
|
||||
lua_pop (L, 1);
|
||||
|
||||
lua_pushvalue (L, 3); /* pass 'steps' table as upvalue */
|
||||
lua_pushcclosure (L, async_event_hook_execute_step, 1);
|
||||
execute_step = wplua_function_to_closure (L, -1);
|
||||
lua_pop (L, 1);
|
||||
|
||||
hook = wp_async_event_hook_new (name, priority, get_next_step, execute_step);
|
||||
hook = wp_async_event_hook_new (name, before, after, get_next_step,
|
||||
execute_step);
|
||||
|
||||
/* clear the lua stack now to make some space */
|
||||
lua_settop (L, 1);
|
||||
|
||||
wplua_pushobject (L, hook);
|
||||
|
||||
lua_pushliteral (L, "interests");
|
||||
if (lua_gettable (L, 1) == LUA_TTABLE) {
|
||||
if (lua_getfield (L, 1, "interests") == LUA_TTABLE) {
|
||||
lua_pushnil (L);
|
||||
while (lua_next (L, -2)) {
|
||||
WpObjectInterest *interest =
|
||||
|
@@ -191,24 +191,11 @@ local Feature = {
|
||||
},
|
||||
}
|
||||
|
||||
local HookPriority = {
|
||||
LOWEST = -500,
|
||||
ULTRA_LOW = -300,
|
||||
VERY_LOW = -200,
|
||||
LOW = -100,
|
||||
NORMAL = 0,
|
||||
HIGH = 100,
|
||||
VERY_HIGH = 200,
|
||||
ULTRA_HIGH = 300,
|
||||
HIGHEST = 500,
|
||||
}
|
||||
|
||||
SANDBOX_EXPORT = {
|
||||
Debug = Debug,
|
||||
Id = Id,
|
||||
Features = Features,
|
||||
Feature = Feature,
|
||||
HookPriority = HookPriority,
|
||||
GLib = GLib,
|
||||
I18n = I18n,
|
||||
Log = WpLog,
|
||||
|
Reference in New Issue
Block a user