1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6
7 #include <Eo.h>
8
9 #include "Ecore.h"
10 #include "ecore_private.h"
11
12 struct _Ecore_Factorized_Idle
13 {
14 Ecore_Task_Cb func;
15 void *data;
16
17 const Efl_Callback_Array_Item *desc;
18
19 short references;
20 Eina_Bool delete_me : 1;
21 };
22
23 void
_ecore_factorized_idle_event_del(void * data,const Efl_Event * event EINA_UNUSED)24 _ecore_factorized_idle_event_del(void *data, const Efl_Event *event EINA_UNUSED)
25 {
26 _ecore_factorized_idle_del(data);
27 }
28
29 void
_ecore_factorized_idle_process(void * data,const Efl_Event * event EINA_UNUSED)30 _ecore_factorized_idle_process(void *data, const Efl_Event *event EINA_UNUSED)
31 {
32 Ecore_Factorized_Idle *idler = data;
33
34 idler->references++;
35 if (!_ecore_call_task_cb(idler->func, idler->data))
36 idler->delete_me = EINA_TRUE;
37 idler->references--;
38
39 if (idler->delete_me &&
40 idler->references == 0)
41 _ecore_factorized_idle_del(idler);
42 }
43
44 static Eina_Mempool *idler_mp = NULL;
45
46 void *
_ecore_factorized_idle_del(Ecore_Idler * idler)47 _ecore_factorized_idle_del(Ecore_Idler *idler)
48 {
49 void *data;
50
51 if (!idler) return NULL;
52 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
53
54 if (idler->references > 0)
55 {
56 idler->delete_me = EINA_TRUE;
57 return idler->data;
58 }
59
60 efl_event_callback_array_del(_mainloop_singleton, idler->desc, idler);
61
62 data = idler->data;
63 eina_mempool_free(idler_mp, idler);
64 return data;
65 }
66
67 Ecore_Factorized_Idle *
_ecore_factorized_idle_add(const Efl_Callback_Array_Item * desc,Ecore_Task_Cb func,const void * data)68 _ecore_factorized_idle_add(const Efl_Callback_Array_Item *desc,
69 Ecore_Task_Cb func,
70 const void *data)
71 {
72 Ecore_Factorized_Idle *ret;
73
74 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
75
76 if (!func)
77 {
78 ERR("callback function must be set up for an object of Ecore_Idler.");
79 return NULL;
80 }
81
82 if (!idler_mp)
83 {
84 idler_mp = eina_mempool_add("chained_mempool", "Ecore_Idle*", NULL, sizeof (Ecore_Factorized_Idle), 23);
85 if (!idler_mp) return NULL;
86 }
87
88 ret = eina_mempool_malloc(idler_mp, sizeof (Ecore_Factorized_Idle));
89 if (!ret) return NULL;
90
91 ret->func = func;
92 ret->data = (void*) data;
93 ret->desc = desc;
94 ret->references = 0;
95 ret->delete_me = EINA_FALSE;
96
97 efl_event_callback_array_add(_mainloop_singleton, desc, ret);
98
99 return ret;
100 }
101
102 /* Specific to Ecore_Idler implementation */
103
104 EFL_CALLBACKS_ARRAY_DEFINE(ecore_idler_callbacks,
105 { EFL_LOOP_EVENT_IDLE, _ecore_factorized_idle_process },
106 { EFL_EVENT_DEL, _ecore_factorized_idle_event_del });
107
108 EAPI Ecore_Idler *
ecore_idler_add(Ecore_Task_Cb func,const void * data)109 ecore_idler_add(Ecore_Task_Cb func,
110 const void *data)
111 {
112 return _ecore_factorized_idle_add(ecore_idler_callbacks(), func, data);
113 }
114
115 EAPI void *
ecore_idler_del(Ecore_Idler * idler)116 ecore_idler_del(Ecore_Idler *idler)
117 {
118 return _ecore_factorized_idle_del(idler);
119 }
120