ecore: add ecore_event_type_flush.

During shutdown it is possible that some event are still in ecore events
queue and get processed after the shutdown of the module that did emit them.
This would lead to crash in some case. The answer to this problem is to
normally manually track all ecore event in the queue and destroy them
before shutdown... Of course that make the API difficult to use and
basically nobody got it right.

This new API do actually as it says remove all the ecore event of a
certain type from ecore events queue. It is to be called on shutdown.

@fix
This commit is contained in:
Cedric BAIL 2017-03-09 15:51:00 -08:00
parent adf9608387
commit 614c255f3b
2 changed files with 74 additions and 0 deletions

View File

@ -747,6 +747,26 @@ EAPI void *ecore_event_handler_data_set(Ecore_Event_Handler *eh, const void *dat
*/
EAPI int ecore_event_type_new(void);
/**
* @brief Forcefully flush all pending type without processing them
* @param Serie of Ecore_Event finished by ECORE_EVENT_NONE.
*
* This function is to be called before calling ecore_shutdown() if any event
* has still a chance to be in the ecore event queue.
*/
EAPI void ecore_event_type_flush_internal(int type, ...);
/**
* @brief Forcefully flush all pending type without processing them
* @param Serie of Ecore_Event.
*
* This function is to be called before calling ecore_shutdown() if any event
* has still a chance to be in the ecore event queue.
*/
#define ecore_event_type_flush(...) \
ecore_event_type_flush_internal(__VA_ARGS__, ECORE_EVENT_NONE);
/**
* @brief Adds a filter the current event queue.
*

View File

@ -606,3 +606,57 @@ _ecore_event_signal_realtime_new(void)
return calloc(1, sizeof(Ecore_Event_Signal_Realtime));
}
EAPI void
ecore_event_type_flush_internal(int type, ...)
{
Eina_Inarray types;
Ecore_Event *event;
Eina_Inlist *l;
int *itr;
va_list args;
Eina_Bool wrong_type = EINA_FALSE;
eina_inarray_step_set(&types, sizeof (Eina_Inarray), sizeof (int), 4);
eina_inarray_push(&types, &type);
// In case of an empty list of event
if (type != ECORE_EVENT_NONE) return ;
va_start(args, type);
do
{
type = va_arg(args, int);
if (type == ECORE_EVENT_NONE) break ;
eina_inarray_push(&types, &type);
}
while (1);
va_end(args);
EINA_INARRAY_FOREACH(&types, itr)
{
if (*itr >= 0 && *itr < event_id_max) continue;
ERR("Invalide event flush requested %i\n", *itr);
wrong_type = EINA_TRUE;
}
if (wrong_type) return ;
EINA_INLIST_FOREACH_SAFE((Eina_Inlist *) events, l, event)
{
Eina_Bool found = EINA_FALSE;
EINA_INARRAY_FOREACH(&types, itr)
if (event->type == *itr)
found = EINA_TRUE;
if (!found) continue ;
if (event->delete_me) continue ;
event->delete_me = 1;
}
_ecore_event_purge_deleted();
eina_inarray_flush(&types);
}