0fa2ddf1d1119742941e6f15bb4ef8f77ae86a2b
[profile/ivi/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
11 struct _Ecore_Idler
12 {
13    EINA_INLIST;
14    ECORE_MAGIC;
15    Ecore_Task_Cb func;
16    void        *data;
17    int          references;
18    Eina_Bool    delete_me : 1;
19 };
20
21
22 static Ecore_Idler *idlers = NULL;
23 static Ecore_Idler *idler_current = NULL;
24 static int          idlers_delete_me = 0;
25
26 /**
27  * Add an idler handler.
28  * @param  func The function to call when idling.
29  * @param  data The data to be passed to this @p func call.
30  * @return A idler handle if successfully added.  NULL otherwise.
31  * @ingroup Idle_Group
32  *
33  * Add an idler handle to the event loop, returning a handle on success and
34  * NULL otherwise.  The function @p func will be called repeatedly while
35  * no other events are ready to be processed, as long as it returns 1
36  * (or ECORE_CALLBACK_RENEW). A return of 0 (or ECORE_CALLBACK_CANCEL) deletes
37  * the idler.
38  *
39  * Idlers are useful for progressively prossessing data without blocking.
40  */
41 EAPI Ecore_Idler *
42 ecore_idler_add(Ecore_Task_Cb func, const void *data)
43 {
44    Ecore_Idler *ie;
45
46    if (!func) return NULL;
47    ie = calloc(1, sizeof(Ecore_Idler));
48    if (!ie) return NULL;
49    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER);
50    ie->func = func;
51    ie->data = (void *)data;
52    idlers = (Ecore_Idler *) eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
53    return ie;
54 }
55
56 /**
57  * Delete an idler callback from the list to be executed.
58  * @param  idler The handle of the idler callback to delete
59  * @return The data pointer passed to the idler callback on success.  NULL
60  *         otherwise.
61  * @ingroup Idle_Group
62  */
63 EAPI void *
64 ecore_idler_del(Ecore_Idler *idler)
65 {
66    if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER))
67      {
68         ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
69                          "ecore_idler_del");
70         return NULL;
71      }
72    EINA_SAFETY_ON_TRUE_RETURN_VAL(idler->delete_me, NULL);
73    idler->delete_me = 1;
74    idlers_delete_me = 1;
75    return idler->data;
76 }
77
78 void
79 _ecore_idler_shutdown(void)
80 {
81    Ecore_Idler *ie;
82    while ((ie = idlers))
83      {
84         idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(idlers));
85         ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
86         free(ie);
87      }
88    idlers_delete_me = 0;
89    idler_current = NULL;
90 }
91
92 int
93 _ecore_idler_call(void)
94 {
95    if (!idler_current)
96      {
97         /* regular main loop, start from head */
98         idler_current = idlers;
99      }
100    else
101      {
102         /* recursive main loop, continue from where we were */
103         idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
104      }
105
106    while (idler_current)
107      {
108         Ecore_Idler *ie = (Ecore_Idler *)idler_current;
109         if (!ie->delete_me)
110           {
111              ie->references++;
112              if (!ie->func(ie->data))
113                {
114                   if (!ie->delete_me) ecore_idler_del(ie);
115                }
116              ie->references--;
117           }
118         if (idler_current) /* may have changed in recursive main loops */
119           idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
120      }
121    if (idlers_delete_me)
122      {
123         Ecore_Idler *l;
124         int deleted_idlers_in_use = 0;
125         for (l = idlers; l;)
126           {
127              Ecore_Idler *ie = l;
128              l = (Ecore_Idler *) EINA_INLIST_GET(l)->next;
129              if (ie->delete_me)
130                {
131                   if (ie->references)
132                     {
133                        deleted_idlers_in_use++;
134                        continue;
135                     }
136
137                   idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
138                   ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
139                   free(ie);
140                }
141           }
142         if (!deleted_idlers_in_use)
143           idlers_delete_me = 0;
144      }
145    if (idlers) return 1;
146    return 0;
147 }
148
149 int
150 _ecore_idler_exist(void)
151 {
152    if (idlers) return 1;
153    return 0;
154 }