diff options
Diffstat (limited to 'libraries/ecore/src/lib/ecore/ecore_idle_exiter.c')
-rw-r--r-- | libraries/ecore/src/lib/ecore/ecore_idle_exiter.c | 176 |
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 | |||
10 | struct _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 | |||
20 | static Ecore_Idle_Exiter *idle_exiters = NULL; | ||
21 | static Ecore_Idle_Exiter *idle_exiter_current = NULL; | ||
22 | static int idle_exiters_delete_me = 0; | ||
23 | |||
24 | static 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 | */ | ||
42 | EAPI Ecore_Idle_Exiter * | ||
43 | ecore_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)); | ||
56 | unlock: | ||
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 | */ | ||
67 | EAPI void * | ||
68 | ecore_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 | |||
88 | static 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 | |||
97 | void | ||
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 | |||
111 | void | ||
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 | |||
170 | int | ||
171 | _ecore_idle_exiter_exist(void) | ||
172 | { | ||
173 | if (idle_exiters) return 1; | ||
174 | return 0; | ||
175 | } | ||
176 | |||