Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore / ecore_idler.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6
7 #include "Ecore.h"
8 #include "ecore_private.h"
9
10 struct _Ecore_Idler
11 {
12    EINA_INLIST;
13                  ECORE_MAGIC;
14    Ecore_Task_Cb func;
15    void         *data;
16    int           references;
17    Eina_Bool     delete_me : 1;
18 };
19 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Idler);
20
21 static Ecore_Idler *idlers = NULL;
22 static Ecore_Idler *idler_current = NULL;
23 static int idlers_delete_me = 0;
24
25 static void *
26 _ecore_idler_del(Ecore_Idler *idler);
27
28 EAPI Ecore_Idler *
29 ecore_idler_add(Ecore_Task_Cb func,
30                 const void   *data)
31 {
32    Ecore_Idler *ie = NULL;
33
34    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
35    _ecore_lock();
36    if (!func) goto unlock;
37    ie = ecore_idler_calloc(1);
38    if (!ie) goto unlock;
39    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER);
40    ie->func = func;
41    ie->data = (void *)data;
42    idlers = (Ecore_Idler *)eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
43 unlock:
44    _ecore_unlock();
45    return ie;
46 }
47
48 EAPI void *
49 ecore_idler_del(Ecore_Idler *idler)
50 {
51    void *data = NULL;
52
53    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
54    if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER))
55      {
56         ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
57                          "ecore_idler_del");
58         return NULL;
59      }
60
61    _ecore_lock();
62    data = _ecore_idler_del(idler);
63    _ecore_unlock();
64    return data;
65 }
66
67 /**
68  * @}
69  */
70
71 /**
72  * @}
73  */
74
75 static void *
76 _ecore_idler_del(Ecore_Idler *idler)
77 {
78    EINA_SAFETY_ON_TRUE_RETURN_VAL(idler->delete_me, NULL);
79    idler->delete_me = 1;
80    idlers_delete_me = 1;
81    return idler->data;
82 }
83
84 void
85 _ecore_idler_shutdown(void)
86 {
87    Ecore_Idler *ie;
88    while ((ie = idlers))
89      {
90         idlers = (Ecore_Idler *)eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(idlers));
91         ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
92         ecore_idler_mp_free(ie);
93      }
94    idlers_delete_me = 0;
95    idler_current = NULL;
96 }
97
98 int
99 _ecore_idler_all_call(void)
100 {
101    if (!idler_current)
102      {
103         /* regular main loop, start from head */
104          idler_current = idlers;
105      }
106    else
107      {
108         /* recursive main loop, continue from where we were */
109          idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
110      }
111
112    while (idler_current)
113      {
114         Ecore_Idler *ie = (Ecore_Idler *)idler_current;
115         if (!ie->delete_me)
116           {
117              ie->references++;
118              if (!_ecore_call_task_cb(ie->func, ie->data))
119                {
120                   if (!ie->delete_me) _ecore_idler_del(ie);
121                }
122              ie->references--;
123           }
124         if (idler_current) /* may have changed in recursive main loops */
125           idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
126      }
127    if (idlers_delete_me)
128      {
129         Ecore_Idler *l;
130         int deleted_idlers_in_use = 0;
131         for (l = idlers; l; )
132           {
133              Ecore_Idler *ie = l;
134              l = (Ecore_Idler *)EINA_INLIST_GET(l)->next;
135              if (ie->delete_me)
136                {
137                   if (ie->references)
138                     {
139                        deleted_idlers_in_use++;
140                        continue;
141                     }
142
143                   idlers = (Ecore_Idler *)eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
144                   ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
145                   ecore_idler_mp_free(ie);
146                }
147           }
148         if (!deleted_idlers_in_use)
149           idlers_delete_me = 0;
150      }
151    if (idlers) return 1;
152    return 0;
153 }
154
155 int
156 _ecore_idler_exist(void)
157 {
158    if (idlers) return 1;
159    return 0;
160 }
161