Tizen 2.0 Release
[profile/ivi/ecore.git] / src / lib / ecore / ecore_idler.c
index ff2dd7e..62998b6 100644 (file)
@@ -1,55 +1,81 @@
-#include "ecore_private.h"
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
 #include "Ecore.h"
+#include "ecore_private.h"
+
+struct _Ecore_Idler
+{
+   EINA_INLIST;
+                 ECORE_MAGIC;
+   Ecore_Task_Cb func;
+   void         *data;
+   int           references;
+   Eina_Bool     delete_me : 1;
+};
+GENERIC_ALLOC_SIZE_DECLARE(Ecore_Idler);
 
 static Ecore_Idler *idlers = NULL;
-static int          idlers_delete_me = 0;
+static Ecore_Idler *idler_current = NULL;
+static int idlers_delete_me = 0;
+
+static void *
+_ecore_idler_del(Ecore_Idler *idler);
 
-/**
- * Add an idler handler.
- * @param  func The function to call when idling.
- * @param  data The data to be passed to this @p func call.
- * @return A idler handle if successfully added.  NULL otherwise.
- * @ingroup Idle_Group
- *
- * Add an idler handle to the event loop, returning a handle on success and
- * NULL otherwise.  The function @p func will be called repeatedly while
- * no other events are ready to be processed, as long as it returns 1 
- * (or ECORE_CALLBACK_RENEW). A return of 0 (or ECORE_CALLBACK_CANCEL) deletes 
- * the idler.
- *
- * Idlers are useful for progressively prossessing data without blocking.
- */
 EAPI Ecore_Idler *
-ecore_idler_add(int (*func) (void *data), const void *data)
+ecore_idler_add(Ecore_Task_Cb func,
+                const void   *data)
 {
-   Ecore_Idler *ie;
+   Ecore_Idler *ie = NULL;
 
-   if (!func) return NULL;
-   ie = calloc(1, sizeof(Ecore_Idler));
-   if (!ie) return NULL;
+   EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
+   _ecore_lock();
+   if (!func) goto unlock;
+   ie = ecore_idler_calloc(1);
+   if (!ie) goto unlock;
    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER);
    ie->func = func;
    ie->data = (void *)data;
-   idlers = _ecore_list2_append(idlers, ie);
+   idlers = (Ecore_Idler *)eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
+unlock:
+   _ecore_unlock();
    return ie;
 }
 
-/**
- * Delete an idler callback from the list to be executed.
- * @param  idler The handle of the idler callback to delete
- * @return The data pointer passed to the idler callback on success.  NULL
- *         otherwise.
- * @ingroup Idle_Group
- */
 EAPI void *
 ecore_idler_del(Ecore_Idler *idler)
 {
+   void *data = NULL;
+
+   EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
    if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER))
      {
-       ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
-                        "ecore_idler_del");
-       return NULL;
+        ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
+                         "ecore_idler_del");
+        return NULL;
      }
+
+   _ecore_lock();
+   data = _ecore_idler_del(idler);
+   _ecore_unlock();
+   return data;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+static void *
+_ecore_idler_del(Ecore_Idler *idler)
+{
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(idler->delete_me, NULL);
    idler->delete_me = 1;
    idlers_delete_me = 1;
    return idler->data;
@@ -58,49 +84,69 @@ ecore_idler_del(Ecore_Idler *idler)
 void
 _ecore_idler_shutdown(void)
 {
-   while (idlers)
+   Ecore_Idler *ie;
+   while ((ie = idlers))
      {
-       Ecore_Idler *ie;
-       
-       ie = idlers;
-       idlers = _ecore_list2_remove(idlers, ie);
-       ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
-       free(ie);
+        idlers = (Ecore_Idler *)eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(idlers));
+        ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+        ecore_idler_mp_free(ie);
      }
    idlers_delete_me = 0;
+   idler_current = NULL;
 }
 
 int
-_ecore_idler_call(void)
+_ecore_idler_all_call(void)
 {
-   Ecore_List2 *l;
+   if (!idler_current)
+     {
+        /* regular main loop, start from head */
+         idler_current = idlers;
+     }
+   else
+     {
+        /* recursive main loop, continue from where we were */
+         idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
+     }
 
-   for (l = (Ecore_List2 *)idlers; l; l = l->next)
+   while (idler_current)
      {
-       Ecore_Idler *ie;
-       
-       ie = (Ecore_Idler *)l;
-       if (!ie->delete_me)
-         {
-            if (!ie->func(ie->data)) ecore_idler_del(ie);
-         }
+        Ecore_Idler *ie = (Ecore_Idler *)idler_current;
+        if (!ie->delete_me)
+          {
+             ie->references++;
+             if (!_ecore_call_task_cb(ie->func, ie->data))
+               {
+                  if (!ie->delete_me) _ecore_idler_del(ie);
+               }
+             ie->references--;
+          }
+        if (idler_current) /* may have changed in recursive main loops */
+          idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
      }
    if (idlers_delete_me)
      {
-       for (l = (Ecore_List2 *)idlers; l;)
-         {
-            Ecore_Idler *ie;
-            
-            ie = (Ecore_Idler *)l;
-            l = l->next;
-            if (ie->delete_me)
-              {
-                 idlers = _ecore_list2_remove(idlers, ie);
-                 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
-                 free(ie);
-              }
-         }
-       idlers_delete_me = 0;
+        Ecore_Idler *l;
+        int deleted_idlers_in_use = 0;
+        for (l = idlers; l; )
+          {
+             Ecore_Idler *ie = l;
+             l = (Ecore_Idler *)EINA_INLIST_GET(l)->next;
+             if (ie->delete_me)
+               {
+                  if (ie->references)
+                    {
+                       deleted_idlers_in_use++;
+                       continue;
+                    }
+
+                  idlers = (Ecore_Idler *)eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
+                  ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+                  ecore_idler_mp_free(ie);
+               }
+          }
+        if (!deleted_idlers_in_use)
+          idlers_delete_me = 0;
      }
    if (idlers) return 1;
    return 0;
@@ -112,3 +158,4 @@ _ecore_idler_exist(void)
    if (idlers) return 1;
    return 0;
 }
+