aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore/ecore_idle_exiter.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/ecore/src/lib/ecore/ecore_idle_exiter.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore/ecore_idle_exiter.c b/libraries/ecore/src/lib/ecore/ecore_idle_exiter.c
new file mode 100644
index 0000000..70c6a7a
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore/ecore_idle_exiter.c
@@ -0,0 +1,176 @@
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_Exiter
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_Exiter *idle_exiters = NULL;
21static Ecore_Idle_Exiter *idle_exiter_current = NULL;
22static int idle_exiters_delete_me = 0;
23
24static void *
25_ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter);
26
27/**
28 * @addtogroup Ecore_Idle_Group
29 *
30 * @{
31 */
32
33/**
34 * Add an idle exiter handler.
35 * @param func The function to call when exiting an idle state.
36 * @param data The data to be passed to the @p func call
37 * @return A handle to the idle exiter callback on success. NULL otherwise.
38 * @note The function func will be called every time the main loop is exiting
39 * idle state, as long as it returns 1 (or ECORE_CALLBACK_RENEW). A return of 0
40 * (or ECORE_CALLBACK_CANCEL) deletes the idle exiter.
41 */
42EAPI Ecore_Idle_Exiter *
43ecore_idle_exiter_add(Ecore_Task_Cb func,
44 const void *data)
45{
46 Ecore_Idle_Exiter *ie = NULL;
47
48 _ecore_lock();
49 if (!func) goto unlock;
50 ie = calloc(1, sizeof(Ecore_Idle_Exiter));
51 if (!ie) goto unlock;
52 ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_EXITER);
53 ie->func = func;
54 ie->data = (void *)data;
55 idle_exiters = (Ecore_Idle_Exiter *)eina_inlist_append(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
56unlock:
57 _ecore_unlock();
58 return ie;
59}
60
61/**
62 * Delete an idle exiter handler from the list to be run on exiting idle state.
63 * @param idle_exiter The idle exiter to delete
64 * @return The data pointer that was being being passed to the handler if
65 * successful. NULL otherwise.
66 */
67EAPI void *
68ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
69{
70 void *data;
71
72 if (!ECORE_MAGIC_CHECK(idle_exiter, ECORE_MAGIC_IDLE_EXITER))
73 {
74 ECORE_MAGIC_FAIL(idle_exiter, ECORE_MAGIC_IDLE_EXITER,
75 "ecore_idle_exiter_del");
76 return NULL;
77 }
78 _ecore_lock();
79 data = _ecore_idle_exiter_del(idle_exiter);
80 _ecore_unlock();
81 return data;
82}
83
84/**
85 * @}
86 */
87
88static void *
89_ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
90{
91 EINA_SAFETY_ON_TRUE_RETURN_VAL(idle_exiter->delete_me, NULL);
92 idle_exiter->delete_me = 1;
93 idle_exiters_delete_me = 1;
94 return idle_exiter->data;
95}
96
97void
98_ecore_idle_exiter_shutdown(void)
99{
100 Ecore_Idle_Exiter *ie;
101 while ((ie = idle_exiters))
102 {
103 idle_exiters = (Ecore_Idle_Exiter *)eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(idle_exiters));
104 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
105 free(ie);
106 }
107 idle_exiters_delete_me = 0;
108 idle_exiter_current = NULL;
109}
110
111void
112_ecore_idle_exiter_call(void)
113{
114 if (!idle_exiter_current)
115 {
116 /* regular main loop, start from head */
117 idle_exiter_current = idle_exiters;
118 }
119 else
120 {
121 /* recursive main loop, continue from where we were */
122 idle_exiter_current =
123 (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
124 }
125
126 while (idle_exiter_current)
127 {
128 Ecore_Idle_Exiter *ie = (Ecore_Idle_Exiter *)idle_exiter_current;
129 if (!ie->delete_me)
130 {
131 ie->references++;
132 if (!_ecore_call_task_cb(ie->func, ie->data))
133 {
134 if (!ie->delete_me) _ecore_idle_exiter_del(ie);
135 }
136 ie->references--;
137 }
138 if (idle_exiter_current) /* may have changed in recursive main loops */
139 idle_exiter_current =
140 (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
141 }
142 if (idle_exiters_delete_me)
143 {
144 Ecore_Idle_Exiter *l;
145 int deleted_idler_exiters_in_use = 0;
146
147 for (l = idle_exiters; l; )
148 {
149 Ecore_Idle_Exiter *ie = l;
150
151 l = (Ecore_Idle_Exiter *)EINA_INLIST_GET(l)->next;
152 if (ie->delete_me)
153 {
154 if (ie->references)
155 {
156 deleted_idler_exiters_in_use++;
157 continue;
158 }
159
160 idle_exiters = (Ecore_Idle_Exiter *)eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
161 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
162 free(ie);
163 }
164 }
165 if (!deleted_idler_exiters_in_use)
166 idle_exiters_delete_me = 0;
167 }
168}
169
170int
171_ecore_idle_exiter_exist(void)
172{
173 if (idle_exiters) return 1;
174 return 0;
175}
176