aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore/ecore_idle_enterer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore/ecore_idle_enterer.c')
-rw-r--r--libraries/ecore/src/lib/ecore/ecore_idle_enterer.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore/ecore_idle_enterer.c b/libraries/ecore/src/lib/ecore/ecore_idle_enterer.c
new file mode 100644
index 0000000..03cd1c4
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore/ecore_idle_enterer.c
@@ -0,0 +1,207 @@
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
10struct _Ecore_Idle_Enterer
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
20static Ecore_Idle_Enterer *idle_enterers = NULL;
21static Ecore_Idle_Enterer *idle_enterer_current = NULL;
22static int idle_enterers_delete_me = 0;
23
24static void *
25_ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer);
26
27/**
28 * @addtogroup Ecore_Idle_Group
29 *
30 * @{
31 */
32
33/**
34 * Add an idle enterer handler.
35 * @param func The function to call when entering an idle state.
36 * @param data The data to be passed to the @p func call
37 * @return A handle to the idle enterer callback if successful. Otherwise,
38 * NULL is returned.
39 * @note The function func will be called every time the main loop is entering
40 * idle state, as long as it returns 1 (or ECORE_CALLBACK_RENEW). A return of 0
41 * (or ECORE_CALLBACK_CANCEL) deletes the idle enterer.
42 */
43EAPI Ecore_Idle_Enterer *
44ecore_idle_enterer_add(Ecore_Task_Cb func,
45 const void *data)
46{
47 Ecore_Idle_Enterer *ie = NULL;
48
49 _ecore_lock();
50
51 if (!func) goto unlock;
52 ie = calloc(1, sizeof(Ecore_Idle_Enterer));
53 if (!ie) goto unlock;
54 ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER);
55 ie->func = func;
56 ie->data = (void *)data;
57 idle_enterers = (Ecore_Idle_Enterer *)eina_inlist_append(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
58unlock:
59 _ecore_unlock();
60 return ie;
61}
62
63/**
64 * Add an idle enterer handler at the start of the list so it gets called earlier than others.
65 * @param func The function to call when entering an idle state.
66 * @param data The data to be passed to the @p func call
67 * @return A handle to the idle enterer callback if successful. Otherwise,
68 * NULL is returned.
69 * @note The function func will be called every time the main loop is entering
70 * idle state, as long as it returns 1 (or ECORE_CALLBACK_RENEW). A return of 0
71 * (or ECORE_CALLBACK_CANCEL) deletes the idle enterer.
72 */
73EAPI Ecore_Idle_Enterer *
74ecore_idle_enterer_before_add(Ecore_Task_Cb func,
75 const void *data)
76{
77 Ecore_Idle_Enterer *ie = NULL;
78
79 _ecore_lock();
80
81 if (!func) goto unlock;
82 ie = calloc(1, sizeof(Ecore_Idle_Enterer));
83 if (!ie) goto unlock;
84 ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER);
85 ie->func = func;
86 ie->data = (void *)data;
87 idle_enterers = (Ecore_Idle_Enterer *)eina_inlist_prepend(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
88unlock:
89 _ecore_unlock();
90 return ie;
91}
92
93/**
94 * Delete an idle enterer callback.
95 * @param idle_enterer The idle enterer to delete
96 * @return The data pointer passed to the idler enterer callback on success.
97 * NULL otherwise.
98 */
99EAPI void *
100ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer)
101{
102 void *data;
103
104 if (!ECORE_MAGIC_CHECK(idle_enterer, ECORE_MAGIC_IDLE_ENTERER))
105 {
106 ECORE_MAGIC_FAIL(idle_enterer, ECORE_MAGIC_IDLE_ENTERER,
107 "ecore_idle_enterer_del");
108 return NULL;
109 }
110 _ecore_lock();
111 data = _ecore_idle_enterer_del(idle_enterer);
112 _ecore_unlock();
113 return data;
114}
115
116/**
117 * @}
118 */
119
120static void *
121_ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer)
122{
123 EINA_SAFETY_ON_TRUE_RETURN_VAL(idle_enterer->delete_me, NULL);
124 idle_enterer->delete_me = 1;
125 idle_enterers_delete_me = 1;
126 return idle_enterer->data;
127}
128
129void
130_ecore_idle_enterer_shutdown(void)
131{
132 Ecore_Idle_Enterer *ie;
133 while ((ie = idle_enterers))
134 {
135 idle_enterers = (Ecore_Idle_Enterer *)eina_inlist_remove(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(idle_enterers));
136 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
137 free(ie);
138 }
139 idle_enterers_delete_me = 0;
140 idle_enterer_current = NULL;
141}
142
143void
144_ecore_idle_enterer_call(void)
145{
146 if (!idle_enterer_current)
147 {
148 /* regular main loop, start from head */
149 idle_enterer_current = idle_enterers;
150 }
151 else
152 {
153 /* recursive main loop, continue from where we were */
154 idle_enterer_current =
155 (Ecore_Idle_Enterer *)EINA_INLIST_GET(idle_enterer_current)->next;
156 }
157
158 while (idle_enterer_current)
159 {
160 Ecore_Idle_Enterer *ie = (Ecore_Idle_Enterer *)idle_enterer_current;
161 if (!ie->delete_me)
162 {
163 ie->references++;
164 if (!_ecore_call_task_cb(ie->func, ie->data))
165 {
166 if (!ie->delete_me) _ecore_idle_enterer_del(ie);
167 }
168 ie->references--;
169 }
170 if (idle_enterer_current) /* may have changed in recursive main loops */
171 idle_enterer_current =
172 (Ecore_Idle_Enterer *)EINA_INLIST_GET(idle_enterer_current)->next;
173 }
174 if (idle_enterers_delete_me)
175 {
176 Ecore_Idle_Enterer *l;
177 int deleted_idler_enterers_in_use = 0;
178
179 for (l = idle_enterers; l; )
180 {
181 Ecore_Idle_Enterer *ie = l;
182 l = (Ecore_Idle_Enterer *)EINA_INLIST_GET(l)->next;
183 if (ie->delete_me)
184 {
185 if (ie->references)
186 {
187 deleted_idler_enterers_in_use++;
188 continue;
189 }
190
191 idle_enterers = (Ecore_Idle_Enterer *)eina_inlist_remove(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
192 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
193 free(ie);
194 }
195 }
196 if (!deleted_idler_enterers_in_use)
197 idle_enterers_delete_me = 0;
198 }
199}
200
201int
202_ecore_idle_enterer_exist(void)
203{
204 if (idle_enterers) return 1;
205 return 0;
206}
207