aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/ecore/ecore_idler.c
blob: d8eadaa273d50693568b210ee99d42f479f5117a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdlib.h>

#include <Eo.h>

#include "Ecore.h"
#include "ecore_private.h"

struct _Ecore_Factorized_Idle
{
   Ecore_Task_Cb func;
   void         *data;

   const Efl_Callback_Array_Item *desc;

   short         references;
   Eina_Bool     delete_me : 1;
};

void
_ecore_factorized_idle_event_del(void *data, const Efl_Event *event EINA_UNUSED)
{
   _ecore_factorized_idle_del(data);
}

void
_ecore_factorized_idle_process(void *data, const Efl_Event *event EINA_UNUSED)
{
   Ecore_Factorized_Idle *idler = data;

   idler->references++;
   if (!_ecore_call_task_cb(idler->func, idler->data))
     idler->delete_me = EINA_TRUE;
   idler->references--;

   if (idler->delete_me &&
       idler->references == 0)
     _ecore_factorized_idle_del(idler);
}

void *
_ecore_factorized_idle_del(Ecore_Idler *idler)
{
   void *data;

   if (!idler) return NULL;
   EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);

   if (idler->references > 0)
     {
        idler->delete_me = EINA_TRUE;
        return idler->data;
     }

   efl_event_callback_array_del(_mainloop_singleton, idler->desc, idler);

   data = idler->data;
   free(idler);
   return data;
}

Ecore_Factorized_Idle *
_ecore_factorized_idle_add(const Efl_Callback_Array_Item *desc,
                           Ecore_Task_Cb func,
                           const void   *data)
{
   Ecore_Factorized_Idle *ret;

   if (EINA_UNLIKELY(!eina_main_loop_is()))
     {
        EINA_MAIN_LOOP_CHECK_RETURN;
     }

   if (!func)
     {
        ERR("callback function must be set up for an object of Ecore_Idler.");
        return NULL;
     }

   ret = malloc(sizeof (Ecore_Idler));
   if (!ret) return NULL;

   ret->func = func;
   ret->data = (void*) data;
   ret->desc = desc;
   ret->references = 0;
   ret->delete_me = EINA_FALSE;

   efl_event_callback_array_add(_mainloop_singleton, desc, ret);

   return ret;
}

/* Specific to Ecore_Idler implementation */

EFL_CALLBACKS_ARRAY_DEFINE(ecore_idler_callbacks,
                          { EFL_LOOP_EVENT_IDLE, _ecore_factorized_idle_process },
                          { EFL_EVENT_DEL, _ecore_factorized_idle_event_del });

EAPI Ecore_Idler *
ecore_idler_add(Ecore_Task_Cb func,
                const void   *data)
{
   return _ecore_factorized_idle_add(ecore_idler_callbacks(), func, data);
}

EAPI void *
ecore_idler_del(Ecore_Idler *idler)
{
   return _ecore_factorized_idle_del(idler);
}

void
_ecore_idler_all_call(Eo *loop)
{
   efl_event_callback_call(loop, EFL_LOOP_EVENT_IDLE, NULL);
}

int
_ecore_idler_exist(Eo *loop)
{
   Efl_Loop_Data *dt = efl_data_scope_get(loop, EFL_LOOP_CLASS);

   return dt->idlers;
}