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 (*func) (void *data, int type, void *event);
void *data;
int references;
Eina_Bool delete_me : 1;
};
@ -31,6 +32,7 @@ struct _Ecore_Event_Filter
void (*func_end) (void *data, void *loop_data);
void *loop_data;
void *data;
int references;
Eina_Bool delete_me : 1;
};
@ -42,6 +44,7 @@ struct _Ecore_Event
void *event;
void (*func_free) (void *data, void *ev);
void *data;
int references;
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_event_purge_deleted(void);
/**
* Add an event handler.
* @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_Filter *ef;
while (events) _ecore_event_del(events);
_ecore_event_purge_deleted();
for (i = 0; i < event_handlers_num; i++)
{
while ((eh = event_handlers[i]))
@ -391,18 +397,34 @@ _ecore_event_del(Ecore_Event *event)
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
_ecore_event_call(void)
{
Ecore_Event *e;
Ecore_Event_Filter *ef;
Ecore_Event_Handler *eh;
int handle_count;
Eina_List *l, *l_next;
EINA_INLIST_FOREACH(event_filters, ef)
{
if (!ef->delete_me)
{
ef->references++;
if (ef->func_start)
ef->loop_data = ef->func_start(ef->data);
EINA_INLIST_FOREACH(events, e)
@ -416,10 +438,13 @@ _ecore_event_call(void)
}
if (ef->func_end)
ef->func_end(ef->data, ef->loop_data);
ef->references--;
}
}
if (event_filters_delete_me)
{
int deleted_in_use = 0;
Ecore_Event_Filter *l;
EINA_INLIST_FOREACH(event_filters, l)
{
@ -427,19 +452,26 @@ _ecore_event_call(void)
l = (Ecore_Event_Filter *) EINA_INLIST_GET(l)->next;
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));
ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
free(ef);
}
}
event_filters_delete_me = 0;
if (!deleted_in_use)
event_filters_delete_me = 0;
}
// printf("EVENT BATCH...\n");
EINA_INLIST_FOREACH(events, e)
{
if (!e->delete_me)
{
handle_count = 0;
int handle_count = 0;
ecore_raw_event_type = e->type;
ecore_raw_event_event = 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)
{
int ret;
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" */
}
}
@ -465,11 +504,14 @@ _ecore_event_call(void)
ecore_raw_event_type = ECORE_EVENT_NONE;
ecore_raw_event_event = NULL;
while (events) _ecore_event_del((Ecore_Event *) events);
EINA_LIST_FREE(event_handlers_delete_list, eh)
_ecore_event_purge_deleted();
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_delete_list = eina_list_remove(event_handlers_delete_list, eh);
ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
free(eh);
}

View File

@ -137,7 +137,6 @@ int _ecore_idle_exiter_exist(void);
void _ecore_event_shutdown(void);
int _ecore_event_exist(void);
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);
Ecore_Timer *_ecore_exe_doomsday_clock_get(Ecore_Exe *exe);