events (also filters and handlers) now have reference counting.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 24 Feb 2010 01:16:00 +0000 (01:16 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 24 Feb 2010 01:16:00 +0000 (01:16 +0000)
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.

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@46417 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/ecore/ecore_events.c
src/lib/ecore/ecore_private.h

index a92dd97..bf01142 100644 (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);
      }
index aa7a754..3865fc3 100644 (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);