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