1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #define EFL_LOOP_PROTECTED
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <math.h>
12 #include <sys/time.h>
13 #include <errno.h>
14
15 #include "Ecore.h"
16 #include "ecore_private.h"
17
18 #include "ecore_main_common.h"
19
20 typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
21 typedef struct _Efl_Internal_Promise Efl_Internal_Promise;
22
23 struct _Efl_Loop_Promise_Simple_Data
24 {
25 union {
26 Efl_Loop_Timer *timer;
27 Ecore_Idler *idler;
28 };
29 Eina_Promise *promise;
30 };
31 GENERIC_ALLOC_SIZE_DECLARE(Efl_Loop_Promise_Simple_Data);
32
33 Eo *_mainloop_singleton = NULL;
34 Efl_Loop_Data *_mainloop_singleton_data = NULL;
35
36 EAPI Eo *
efl_main_loop_get(void)37 efl_main_loop_get(void)
38 {
39 return efl_app_main_get();
40 }
41
42 EOLIAN static void
_efl_loop_iterate(Eo * obj,Efl_Loop_Data * pd)43 _efl_loop_iterate(Eo *obj, Efl_Loop_Data *pd)
44 {
45 _ecore_main_loop_iterate(obj, pd);
46 }
47
48 EOLIAN static int
_efl_loop_iterate_may_block(Eo * obj,Efl_Loop_Data * pd,int may_block)49 _efl_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block)
50 {
51 return _ecore_main_loop_iterate_may_block(obj, pd, may_block);
52 }
53
54 EOLIAN static Eina_Value *
_efl_loop_begin(Eo * obj,Efl_Loop_Data * pd)55 _efl_loop_begin(Eo *obj, Efl_Loop_Data *pd)
56 {
57 _ecore_main_loop_begin(obj, pd);
58 if (pd->thread_children)
59 {
60 Eina_List *l, *ll;
61 Eo *child;
62
63 // request all child threads to die and defer the quit until
64 // the children have all died and returned.
65 // run main loop again to clean out children and their exits
66 pd->quit_on_last_thread_child_del = EINA_TRUE;
67 EINA_LIST_FOREACH_SAFE(pd->thread_children, l, ll, child)
68 {
69 Efl_Task_Flags task_flags = efl_task_flags_get(child);
70
71 if (task_flags & EFL_TASK_FLAGS_EXIT_WITH_PARENT)
72 efl_task_end(child);
73 else
74 _efl_thread_child_remove(obj, pd, child);
75 }
76 if (pd->thread_children) _ecore_main_loop_begin(obj, pd);
77 }
78 return &(pd->exit_code);
79 }
80
81 EOLIAN static void
_efl_loop_quit(Eo * obj,Efl_Loop_Data * pd,Eina_Value exit_code)82 _efl_loop_quit(Eo *obj, Efl_Loop_Data *pd, Eina_Value exit_code)
83 {
84 _ecore_main_loop_quit(obj, pd);
85 pd->exit_code = exit_code;
86 }
87
88 EOLIAN static void
_efl_loop_time_set(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,double t)89 _efl_loop_time_set(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double t)
90 {
91 pd->loop_time = t;
92 }
93
94 EOLIAN static double
_efl_loop_time_get(const Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)95 _efl_loop_time_get(const Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
96 {
97 return pd->loop_time;
98 }
99
100 EAPI void
efl_exit(int exit_code)101 efl_exit(int exit_code)
102 {
103 Eina_Value v = EINA_VALUE_EMPTY;
104
105 eina_value_setup(&v, EINA_VALUE_TYPE_INT);
106 eina_value_set(&v, exit_code);
107 efl_loop_quit(efl_main_loop_get(), v);
108 }
109
110 EAPI int
efl_loop_exit_code_process(Eina_Value * value)111 efl_loop_exit_code_process(Eina_Value *value)
112 {
113 Eina_Value def = EINA_VALUE_EMPTY;
114 const Eina_Value_Type *t;
115 int r = 0;
116
117 if (value == NULL ||
118 !value->type)
119 {
120 def = eina_value_int_init(0);
121 value = &def;
122 }
123
124 t = eina_value_type_get(value);
125
126 if (t == EINA_VALUE_TYPE_UCHAR ||
127 t == EINA_VALUE_TYPE_USHORT ||
128 t == EINA_VALUE_TYPE_UINT ||
129 t == EINA_VALUE_TYPE_ULONG ||
130 t == EINA_VALUE_TYPE_UINT64 ||
131 t == EINA_VALUE_TYPE_CHAR ||
132 t == EINA_VALUE_TYPE_SHORT ||
133 t == EINA_VALUE_TYPE_INT ||
134 t == EINA_VALUE_TYPE_LONG ||
135 t == EINA_VALUE_TYPE_INT64 ||
136 t == EINA_VALUE_TYPE_FLOAT ||
137 t == EINA_VALUE_TYPE_DOUBLE)
138 {
139 Eina_Value v = EINA_VALUE_EMPTY;
140
141 eina_value_setup(&v, EINA_VALUE_TYPE_INT);
142 if (!eina_value_convert(value, &v)) r = -1;
143 else eina_value_get(&v, &r);
144 }
145 else
146 {
147 FILE *out = stdout;
148 char *msg;
149
150 msg = eina_value_to_string(value);
151
152 if (t == EINA_VALUE_TYPE_ERROR)
153 {
154 r = -1;
155 out = stderr;
156 }
157 fprintf(out, "%s\n", msg);
158 free(msg);
159 }
160 return r;
161 }
162
163 static void
_poll_trigger(void * data,const Efl_Event * event)164 _poll_trigger(void *data, const Efl_Event *event)
165 {
166 Eo *parent = efl_parent_get(event->object);
167
168 efl_event_callback_call(parent, data, NULL);
169 }
170
171 static void
_check_event_catcher_add(void * data,const Efl_Event * event)172 _check_event_catcher_add(void *data, const Efl_Event *event)
173 {
174 const Efl_Callback_Array_Item_Full *array = event->info;
175 Efl_Loop_Data *pd = data;
176 int i;
177
178 for (i = 0; array[i].desc != NULL; i++)
179 {
180 if (array[i].desc == EFL_LOOP_EVENT_IDLE)
181 {
182 ++pd->idlers;
183 }
184 // XXX: all the below are kind of bad. ecore_pollers were special.
185 // they all woke up at the SAME time based on interval, (all pollers
186 // of interval 1 woke up together, those with 2 woke up when 1 and
187 // 2 woke up, 4 woke up together along with 1 and 2 etc.
188 // the below means they will just go off whenever but at a pre
189 // defined interval - 1/60th, 6 and 66 seconds. not really great
190 // pollers probably should be less frequent that 1/60th even on poll
191 // high, medium probably down to 1-2 sec and low - yes maybe 30 or 60
192 // sec... still - not timed to wake up together. :(
193 else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH)
194 {
195 if (!pd->poll_high)
196 {
197 // Would be better to have it in sync with normal wake up
198 // of the main loop for better energy efficiency, I guess.
199 pd->poll_high = efl_add
200 (EFL_LOOP_TIMER_CLASS, event->object,
201 efl_event_callback_add(efl_added,
202 EFL_LOOP_TIMER_EVENT_TIMER_TICK,
203 _poll_trigger,
204 EFL_LOOP_EVENT_POLL_HIGH),
205 efl_loop_timer_interval_set(efl_added, 1.0 / 60.0));
206 }
207 ++pd->pollers.high;
208 }
209 else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM)
210 {
211 if (!pd->poll_medium)
212 {
213 pd->poll_medium = efl_add
214 (EFL_LOOP_TIMER_CLASS, event->object,
215 efl_event_callback_add(efl_added,
216 EFL_LOOP_TIMER_EVENT_TIMER_TICK,
217 _poll_trigger,
218 EFL_LOOP_EVENT_POLL_MEDIUM),
219 efl_loop_timer_interval_set(efl_added, 6));
220 }
221 ++pd->pollers.medium;
222 }
223 else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW)
224 {
225 if (!pd->poll_low)
226 {
227 pd->poll_low = efl_add
228 (EFL_LOOP_TIMER_CLASS, event->object,
229 efl_event_callback_add(efl_added,
230 EFL_LOOP_TIMER_EVENT_TIMER_TICK,
231 _poll_trigger,
232 EFL_LOOP_EVENT_POLL_LOW),
233 efl_loop_timer_interval_set(efl_added, 66));
234 }
235 ++pd->pollers.low;
236 }
237 }
238 }
239
240 static void
_check_event_catcher_del(void * data,const Efl_Event * event)241 _check_event_catcher_del(void *data, const Efl_Event *event)
242 {
243 const Efl_Callback_Array_Item_Full *array = event->info;
244 Efl_Loop_Data *pd = data;
245 int i;
246
247 for (i = 0; array[i].desc != NULL; i++)
248 {
249 if (array[i].desc == EFL_LOOP_EVENT_IDLE)
250 {
251 --pd->idlers;
252 }
253 else if (array[i].desc == EFL_LOOP_EVENT_POLL_HIGH)
254 {
255 --pd->pollers.high;
256 if (!pd->pollers.high)
257 {
258 efl_del(pd->poll_high);
259 pd->poll_high = NULL;
260 }
261 }
262 else if (array[i].desc == EFL_LOOP_EVENT_POLL_MEDIUM)
263 {
264 --pd->pollers.medium;
265 if (!pd->pollers.medium)
266 {
267 efl_del(pd->poll_medium);
268 pd->poll_medium = NULL;
269 }
270 }
271 else if (array[i].desc == EFL_LOOP_EVENT_POLL_LOW)
272 {
273 --pd->pollers.low;
274 if (!pd->pollers.low)
275 {
276 efl_del(pd->poll_low);
277 pd->poll_low = NULL;
278 }
279 }
280 }
281 }
282
283 EFL_CALLBACKS_ARRAY_DEFINE(event_catcher_watch,
284 { EFL_EVENT_CALLBACK_ADD, _check_event_catcher_add },
285 { EFL_EVENT_CALLBACK_DEL, _check_event_catcher_del });
286
287 EOLIAN static Efl_Object *
_efl_loop_efl_object_constructor(Eo * obj,Efl_Loop_Data * pd)288 _efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd)
289 {
290 obj = efl_constructor(efl_super(obj, EFL_LOOP_CLASS));
291 if (!obj) return NULL;
292
293 efl_event_callback_array_add(obj, event_catcher_watch(), pd);
294
295 pd->loop_time = ecore_time_get();
296 pd->epoll_fd = -1;
297 pd->timer_fd = -1;
298 pd->future_message_handler = efl_add(EFL_LOOP_MESSAGE_FUTURE_HANDLER_CLASS, obj);
299 efl_provider_register(obj, EFL_LOOP_MESSAGE_FUTURE_HANDLER_CLASS, pd->future_message_handler);
300
301 return obj;
302 }
303
304 EOLIAN static void
_efl_loop_efl_object_invalidate(Eo * obj,Efl_Loop_Data * pd)305 _efl_loop_efl_object_invalidate(Eo *obj, Efl_Loop_Data *pd)
306 {
307 efl_invalidate(efl_super(obj, EFL_LOOP_CLASS));
308
309 _ecore_main_content_clear(obj, pd);
310
311 pd->poll_low = NULL;
312 pd->poll_medium = NULL;
313 pd->poll_high = NULL;
314
315 // After invalidate, it won't be possible to parent to the singleton anymore
316 if (obj == _mainloop_singleton)
317 {
318 _mainloop_singleton = NULL;
319 _mainloop_singleton_data = NULL;
320 }
321 }
322
323 EOLIAN static void
_efl_loop_efl_object_destructor(Eo * obj,Efl_Loop_Data * pd)324 _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
325 {
326 pd->future_message_handler = NULL;
327 while (pd->thread_children)
328 _efl_thread_child_remove(obj, pd, pd->thread_children->data);
329 efl_destructor(efl_super(obj, EFL_LOOP_CLASS));
330 }
331
332 static Eina_Value
_efl_loop_arguments_send(Eo * o EINA_UNUSED,void * data,const Eina_Value v)333 _efl_loop_arguments_send(Eo *o EINA_UNUSED, void *data, const Eina_Value v)
334
335 {
336 static Eina_Bool initialization = EINA_TRUE;
337 Efl_Loop_Arguments arge;
338 Eina_Array *arga = data;
339
340 arge.argv = arga;
341 arge.initialization = initialization;
342 initialization = EINA_FALSE;
343
344 efl_event_callback_call(efl_main_loop_get(),
345 EFL_LOOP_EVENT_ARGUMENTS, &arge);
346 return v;
347 }
348
349 static void
_efl_loop_arguments_cleanup(Eo * o EINA_UNUSED,void * data,const Eina_Future * dead_future EINA_UNUSED)350 _efl_loop_arguments_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
351 {
352 Eina_Array *arga = data;
353 Eina_Stringshare *s;
354
355 while ((s = eina_array_pop(arga))) eina_stringshare_del(s);
356 eina_array_free(arga);
357 }
358
359 // It doesn't make sense to send those argument to any other mainloop
360 // As it also doesn't make sense to allow anyone to override this, so
361 // should be internal for sure, not even protected.
362 EAPI void
ecore_loop_arguments_send(int argc,const char ** argv)363 ecore_loop_arguments_send(int argc, const char **argv)
364 {
365 Eina_Array *arga, *cml;
366 int i = 0;
367
368 arga = eina_array_new(argc);
369 cml = eina_array_new(argc);
370 for (i = 0; i < argc; i++)
371 {
372 Eina_Stringshare *arg;
373
374 arg = eina_stringshare_add(argv[i]);
375 eina_array_push(arga, arg);
376 arg = eina_stringshare_add(argv[i]);
377 eina_array_push(cml, arg);
378 }
379
380 efl_core_command_line_command_array_set(efl_app_main_get(), cml);
381 efl_future_then(efl_main_loop_get(), efl_loop_job(efl_main_loop_get()),
382 .success = _efl_loop_arguments_send,
383 .free = _efl_loop_arguments_cleanup,
384 .data = arga);
385 }
386
387 static Eina_Future *
_efl_loop_job(Eo * obj,Efl_Loop_Data * pd EINA_UNUSED)388 _efl_loop_job(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
389 {
390 // NOTE: Eolian should do efl_future_then() to bind future to object.
391 return efl_future_then(obj,
392 eina_future_resolved(efl_loop_future_scheduler_get(obj), EINA_VALUE_EMPTY));
393 }
394
395 EOLIAN static void
_efl_loop_throttle_set(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,double amount)396 _efl_loop_throttle_set(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double amount)
397 {
398 pd->throttle = ((double)amount) * 1000000.0;
399 }
400
401 EOLIAN static double
_efl_loop_throttle_get(const Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)402 _efl_loop_throttle_get(const Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
403 {
404 return (double)(pd->throttle) / 1000000.0;
405 }
406
407 static void
_efl_loop_idle_cancel(void * data,const Eina_Promise * dead_ptr EINA_UNUSED)408 _efl_loop_idle_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
409 {
410 Efl_Loop_Promise_Simple_Data *d = data;
411
412 ecore_idler_del(d->idler);
413 d->idler = NULL;
414 d->promise = NULL;
415 efl_loop_promise_simple_data_mp_free(d);
416 }
417
418 static Eina_Bool
_efl_loop_idle_done(void * data)419 _efl_loop_idle_done(void *data)
420 {
421 Efl_Loop_Promise_Simple_Data *d = data;
422 eina_promise_resolve(d->promise, EINA_VALUE_EMPTY);
423 d->idler = NULL;
424 d->promise = NULL;
425 efl_loop_promise_simple_data_mp_free(d);
426 return EINA_FALSE;
427 }
428
429 static Eina_Future *
_efl_loop_idle(Eo * obj,Efl_Loop_Data * pd EINA_UNUSED)430 _efl_loop_idle(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
431 {
432 Efl_Loop_Promise_Simple_Data *d;
433 Eina_Promise *p;
434 Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj);
435
436 d = efl_loop_promise_simple_data_calloc(1);
437 EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
438
439 d->idler = ecore_idler_add(_efl_loop_idle_done, d);
440 EINA_SAFETY_ON_NULL_GOTO(d->idler, idler_error);
441
442 p = eina_promise_new(sched, _efl_loop_idle_cancel, d);
443 // d is dead if p is NULL
444 EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
445 d->promise = p;
446
447 // NOTE: Eolian should do efl_future_then() to bind future to object.
448 return efl_future_then(obj, eina_future_new(p));
449
450 idler_error:
451 d->idler = NULL;
452 d->promise = NULL;
453 efl_loop_promise_simple_data_mp_free(d);
454 return NULL;
455 }
456
457 static void
_efl_loop_timeout_cancel(void * data,const Eina_Promise * dead_ptr EINA_UNUSED)458 _efl_loop_timeout_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
459 {
460 Efl_Loop_Promise_Simple_Data *d = data;
461
462 if (d->timer)
463 efl_del(d->timer);
464 }
465
466 static void
_efl_loop_timeout_done(void * data,const Efl_Event * event)467 _efl_loop_timeout_done(void *data, const Efl_Event *event)
468 {
469 Efl_Loop_Promise_Simple_Data *d = data;
470
471 eina_promise_resolve(d->promise, EINA_VALUE_EMPTY);
472 d->timer = NULL;
473 efl_del(event->object);
474 }
475
476 static void
_efl_loop_timeout_del(void * data,const Efl_Event * event EINA_UNUSED)477 _efl_loop_timeout_del(void *data, const Efl_Event *event EINA_UNUSED)
478 {
479 Efl_Loop_Promise_Simple_Data *d = data;
480
481 d->timer = NULL;
482 d->promise = NULL;
483 efl_loop_promise_simple_data_mp_free(d);
484 }
485
486 static Eina_Future *
_efl_loop_timeout(Eo * obj,Efl_Loop_Data * pd EINA_UNUSED,double tim)487 _efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double tim)
488 {
489 Efl_Loop_Promise_Simple_Data *d;
490 Eina_Promise *p;
491 Eina_Future_Scheduler *sched = efl_loop_future_scheduler_get(obj);
492
493 d = efl_loop_promise_simple_data_calloc(1);
494 EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
495
496 d->timer = efl_add(EFL_LOOP_TIMER_CLASS, obj,
497 efl_loop_timer_interval_set(efl_added, tim),
498 efl_event_callback_add(efl_added,
499 EFL_LOOP_TIMER_EVENT_TIMER_TICK,
500 _efl_loop_timeout_done, d),
501 efl_event_callback_add(efl_added,
502 EFL_EVENT_DEL,
503 _efl_loop_timeout_del, d)
504 );
505 EINA_SAFETY_ON_NULL_GOTO(d->timer, timer_error);
506
507 p = eina_promise_new(sched, _efl_loop_timeout_cancel, d);
508 // d is dead if p is NULL
509 EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
510 d->promise = p;
511
512 // NOTE: Eolian should do efl_future_then() to bind future to object.
513 return efl_future_then(obj, eina_future_new(p));
514
515 timer_error:
516 d->timer = NULL;
517 d->promise = NULL;
518 efl_loop_promise_simple_data_mp_free(d);
519 return NULL;
520 }
521
522 static Eina_Bool
_efl_loop_register(Eo * obj,Efl_Loop_Data * pd EINA_UNUSED,const Efl_Class * klass,const Efl_Object * provider)523 _efl_loop_register(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED,
524 const Efl_Class *klass, const Efl_Object *provider)
525 {
526 return efl_provider_register(obj, klass, provider);
527 }
528
529 EFL_FUNC_BODYV(efl_loop_register, Eina_Bool, EINA_FALSE, EFL_FUNC_CALL(klass, provider), const Efl_Class *klass, const Efl_Object *provider);
530
531 static Eina_Bool
_efl_loop_unregister(Eo * obj,Efl_Loop_Data * pd EINA_UNUSED,const Efl_Class * klass,const Efl_Object * provider)532 _efl_loop_unregister(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED,
533 const Efl_Class *klass, const Efl_Object *provider)
534 {
535 return efl_provider_unregister(obj, klass, provider);
536 }
537
538 EFL_FUNC_BODYV(efl_loop_unregister, Eina_Bool, EINA_FALSE, EFL_FUNC_CALL(klass, provider), const Efl_Class *klass, const Efl_Object *provider);
539
540 void
_efl_loop_messages_filter(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,void * handler_pd)541 _efl_loop_messages_filter(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, void *handler_pd)
542 {
543 Message *msg;
544
545 pd->message_walking++;
546 EINA_INLIST_FOREACH(pd->message_queue, msg)
547 {
548 if ((msg->handler) && (msg->message) && (!msg->delete_me))
549 {
550 if (!_ecore_event_do_filter(handler_pd,
551 msg->handler, msg->message))
552 {
553 efl_del(msg->message);
554 msg->handler = NULL;
555 msg->message = NULL;
556 msg->delete_me = EINA_TRUE;
557 }
558 }
559 }
560 pd->message_walking--;
561 }
562
563 void
_efl_loop_messages_call(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,void * func,void * data)564 _efl_loop_messages_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, void *func, void *data)
565 {
566 Message *msg;
567
568 pd->message_walking++;
569 EINA_INLIST_FOREACH(pd->message_queue, msg)
570 {
571 if ((msg->handler) && (msg->message) && (!msg->delete_me))
572 {
573 Eina_Bool (*fn) (void *data, void *handler, void *msg);
574
575 fn = func;
576 if (!fn(data, msg->handler, msg->message))
577 {
578 efl_del(msg->message);
579 msg->handler = NULL;
580 msg->message = NULL;
581 msg->delete_me = EINA_TRUE;
582 }
583 }
584 }
585 pd->message_walking--;
586 }
587
588 EOLIAN static Eina_Bool
_efl_loop_message_process(Eo * obj,Efl_Loop_Data * pd)589 _efl_loop_message_process(Eo *obj, Efl_Loop_Data *pd)
590 {
591 if (!pd->message_queue) return EINA_FALSE;
592 pd->message_walking++;
593 _ecore_event_filters_call(obj, pd);
594 while (pd->message_queue)
595 {
596 Message *msg = (Message *)pd->message_queue;
597 if (!msg->delete_me)
598 efl_loop_message_handler_message_call(msg->handler, msg->message);
599 else
600 {
601 if (msg->message) efl_del(msg->message);
602 pd->message_queue =
603 eina_inlist_remove(pd->message_queue,
604 pd->message_queue);
605 free(msg);
606 }
607 }
608 pd->message_walking--;
609 if (pd->message_walking == 0)
610 {
611 Message *msg;
612
613 EINA_INLIST_FREE(pd->message_queue, msg)
614 {
615 if (msg->message)
616 {
617 if (!msg->delete_me)
618 ERR("Found unprocessed event msg=%p handler=%p on queue",
619 msg->message, msg->handler);
620 efl_del(msg->message);
621 }
622 else free(msg);
623 }
624
625 while (pd->message_pending_queue)
626 {
627 msg = (Message *)pd->message_pending_queue;
628 pd->message_pending_queue = eina_inlist_remove(pd->message_pending_queue,
629 pd->message_pending_queue);
630 pd->message_queue = eina_inlist_append(pd->message_queue, EINA_INLIST_GET(msg));
631 }
632 }
633 return EINA_TRUE;
634 }
635
636 EOAPI EFL_FUNC_BODY(efl_loop_message_process, Eina_Bool, 0);
637
638 EWAPI void
efl_build_version_set(int vmaj,int vmin,int vmic,int revision,const char * flavor,const char * build_id)639 efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
640 const char *flavor, const char *build_id)
641 {
642 // note: EFL has not been initialized yet at this point (ie. no eina call)
643 _app_efl_version.major = vmaj;
644 _app_efl_version.minor = vmin;
645 _app_efl_version.micro = vmic;
646 _app_efl_version.revision = revision;
647 free((char *)_app_efl_version.flavor);
648 free((char *)_app_efl_version.build_id);
649 _app_efl_version.flavor = flavor ? strdup(flavor) : NULL;
650 _app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
651 }
652
653 EOLIAN static Eina_Bool
_efl_loop_efl_task_run(Eo * obj,Efl_Loop_Data * pd EINA_UNUSED)654 _efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
655 {
656 efl_loop_exit_code_process(efl_loop_begin(obj));
657 return EINA_TRUE;
658 }
659
660 EOLIAN static void
_efl_loop_efl_task_end(Eo * obj,Efl_Loop_Data * pd EINA_UNUSED)661 _efl_loop_efl_task_end(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
662 {
663 efl_loop_quit(obj, eina_value_int_init(0));
664 }
665
666 EFL_SCHEDULER_ARRAY_DEFINE(loop_scheduler,
667 EFL_LOOP_EVENT_IDLE_ENTER,
668 EFL_LOOP_EVENT_IDLE);
669
670 EAPI Eina_Future_Scheduler *
efl_loop_future_scheduler_get(const Eo * obj)671 efl_loop_future_scheduler_get(const Eo *obj)
672 {
673 Efl_Loop *loop;
674
675 if (!obj) return NULL;
676
677 if (efl_isa(obj, EFL_LOOP_CLASS))
678 {
679 Efl_Loop_Data *pd = efl_data_scope_get(obj, EFL_LOOP_CLASS);
680
681 if (!pd) return NULL;
682 return efl_event_future_scheduler_get(obj, loop_scheduler());
683 }
684 if (efl_isa(obj, EFL_LOOP_CONSUMER_CLASS))
685 return efl_loop_future_scheduler_get(efl_loop_get(obj));
686
687 loop = efl_provider_find(obj, EFL_LOOP_CLASS);
688 if (loop)
689 return efl_loop_future_scheduler_get(loop);
690
691 return NULL;
692 }
693
694 #define EFL_LOOP_EXTRA_OPS \
695 EFL_OBJECT_OP_FUNC(efl_loop_message_process, _efl_loop_message_process), \
696 EFL_OBJECT_OP_FUNC(efl_loop_register, _efl_loop_register), \
697 EFL_OBJECT_OP_FUNC(efl_loop_unregister, _efl_loop_unregister)
698
699 #include "efl_loop.eo.c"
700