events (also filters and handlers) now have reference counting.

Add reference counting to events, event filters and event handlers so
they can recurse main loops.

Note that the required "continuation" when entering main loops is not
there, thus recursion will restart and this will fail badly in lots of
cases. This should be fixed in future commits.



SVN revision: 46417
This commit is contained in:
Gustavo Sverzut Barbieri 2010-02-24 01:16:00 +00:00
parent 0bdbf9d147
commit b9c3b58561
2 changed files with 50 additions and 9 deletions

View File

@ -19,6 +19,7 @@ struct _Ecore_Event_Handler
int type; int type;
int (*func) (void *data, int type, void *event); int (*func) (void *data, int type, void *event);
void *data; void *data;
int references;
Eina_Bool delete_me : 1; Eina_Bool delete_me : 1;
}; };
@ -31,6 +32,7 @@ struct _Ecore_Event_Filter
void (*func_end) (void *data, void *loop_data); void (*func_end) (void *data, void *loop_data);
void *loop_data; void *loop_data;
void *data; void *data;
int references;
Eina_Bool delete_me : 1; Eina_Bool delete_me : 1;
}; };
@ -42,6 +44,7 @@ struct _Ecore_Event
void *event; void *event;
void (*func_free) (void *data, void *ev); void (*func_free) (void *data, void *ev);
void *data; void *data;
int references;
Eina_Bool delete_me : 1; Eina_Bool delete_me : 1;
}; };
@ -61,6 +64,9 @@ static int ecore_raw_event_type = ECORE_EVENT_NONE;
static void *ecore_raw_event_event = NULL; static void *ecore_raw_event_event = NULL;
static void _ecore_event_purge_deleted(void);
/** /**
* Add an event handler. * Add an event handler.
* @param type The type of the event this handler will get called for * @param type The type of the event this handler will get called for
@ -328,7 +334,7 @@ _ecore_event_shutdown(void)
Ecore_Event_Handler *eh; Ecore_Event_Handler *eh;
Ecore_Event_Filter *ef; Ecore_Event_Filter *ef;
while (events) _ecore_event_del(events); _ecore_event_purge_deleted();
for (i = 0; i < event_handlers_num; i++) for (i = 0; i < event_handlers_num; i++)
{ {
while ((eh = event_handlers[i])) while ((eh = event_handlers[i]))
@ -391,18 +397,34 @@ _ecore_event_del(Ecore_Event *event)
return data; return data;
} }
static void
_ecore_event_purge_deleted(void)
{
Ecore_Event *itr = events;
while (itr)
{
Ecore_Event *next = (Ecore_Event *)EINA_INLIST_GET(itr)->next;
if (!itr->references)
_ecore_event_del(itr);
itr = next;
}
}
void void
_ecore_event_call(void) _ecore_event_call(void)
{ {
Ecore_Event *e; Ecore_Event *e;
Ecore_Event_Filter *ef; Ecore_Event_Filter *ef;
Ecore_Event_Handler *eh; Ecore_Event_Handler *eh;
int handle_count; Eina_List *l, *l_next;
EINA_INLIST_FOREACH(event_filters, ef) EINA_INLIST_FOREACH(event_filters, ef)
{ {
if (!ef->delete_me) if (!ef->delete_me)
{ {
ef->references++;
if (ef->func_start) if (ef->func_start)
ef->loop_data = ef->func_start(ef->data); ef->loop_data = ef->func_start(ef->data);
EINA_INLIST_FOREACH(events, e) EINA_INLIST_FOREACH(events, e)
@ -416,10 +438,13 @@ _ecore_event_call(void)
} }
if (ef->func_end) if (ef->func_end)
ef->func_end(ef->data, ef->loop_data); ef->func_end(ef->data, ef->loop_data);
ef->references--;
} }
} }
if (event_filters_delete_me) if (event_filters_delete_me)
{ {
int deleted_in_use = 0;
Ecore_Event_Filter *l; Ecore_Event_Filter *l;
EINA_INLIST_FOREACH(event_filters, l) EINA_INLIST_FOREACH(event_filters, l)
{ {
@ -427,19 +452,26 @@ _ecore_event_call(void)
l = (Ecore_Event_Filter *) EINA_INLIST_GET(l)->next; l = (Ecore_Event_Filter *) EINA_INLIST_GET(l)->next;
if (ef->delete_me) if (ef->delete_me)
{ {
if (ef->references)
{
deleted_in_use++;
continue;
}
event_filters = (Ecore_Event_Filter *) eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef)); event_filters = (Ecore_Event_Filter *) eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE); ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
free(ef); free(ef);
} }
} }
event_filters_delete_me = 0; if (!deleted_in_use)
event_filters_delete_me = 0;
} }
// printf("EVENT BATCH...\n"); // printf("EVENT BATCH...\n");
EINA_INLIST_FOREACH(events, e) EINA_INLIST_FOREACH(events, e)
{ {
if (!e->delete_me) if (!e->delete_me)
{ {
handle_count = 0; int handle_count = 0;
ecore_raw_event_type = e->type; ecore_raw_event_type = e->type;
ecore_raw_event_event = e->event; ecore_raw_event_event = e->event;
// printf("HANDLE ev type %i, %p\n", e->type, e->event); // printf("HANDLE ev type %i, %p\n", e->type, e->event);
@ -449,8 +481,15 @@ _ecore_event_call(void)
{ {
if (!eh->delete_me) if (!eh->delete_me)
{ {
int ret;
handle_count++; handle_count++;
if (!eh->func(eh->data, e->type, e->event))
eh->references++;
ret = eh->func(eh->data, e->type, e->event);
eh->references--;
if (!ret)
break; /* 0 == "call no further handlers" */ break; /* 0 == "call no further handlers" */
} }
} }
@ -465,11 +504,14 @@ _ecore_event_call(void)
ecore_raw_event_type = ECORE_EVENT_NONE; ecore_raw_event_type = ECORE_EVENT_NONE;
ecore_raw_event_event = NULL; ecore_raw_event_event = NULL;
while (events) _ecore_event_del((Ecore_Event *) events); _ecore_event_purge_deleted();
EINA_LIST_FREE(event_handlers_delete_list, eh) EINA_LIST_FOREACH_SAFE(event_handlers_delete_list, l, l_next, eh)
{ {
if (eh->references) continue;
event_handlers_delete_list = eina_list_remove_list(event_handlers_delete_list, l);
event_handlers[eh->type] = (Ecore_Event_Handler *) eina_inlist_remove(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh)); event_handlers[eh->type] = (Ecore_Event_Handler *) eina_inlist_remove(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh));
event_handlers_delete_list = eina_list_remove(event_handlers_delete_list, eh);
ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE); ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
free(eh); free(eh);
} }

View File

@ -137,7 +137,6 @@ int _ecore_idle_exiter_exist(void);
void _ecore_event_shutdown(void); void _ecore_event_shutdown(void);
int _ecore_event_exist(void); int _ecore_event_exist(void);
Ecore_Event *_ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data); Ecore_Event *_ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data);
void *_ecore_event_del(Ecore_Event *event);
void _ecore_event_call(void); void _ecore_event_call(void);
Ecore_Timer *_ecore_exe_doomsday_clock_get(Ecore_Exe *exe); Ecore_Timer *_ecore_exe_doomsday_clock_get(Ecore_Exe *exe);