[ecore] merged svn latest code (svn54830)
[profile/ivi/ecore.git] / src / lib / ecore / ecore_idle_exiter.c
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
11 struct _Ecore_Idle_Exiter
12 {
13    EINA_INLIST;
14    ECORE_MAGIC;
15    Ecore_Task_Cb func;
16    void        *data;
17    int          references;
18    Eina_Bool    delete_me : 1;
19 };
20
21
22 static Ecore_Idle_Exiter *idle_exiters = NULL;
23 static Ecore_Idle_Exiter *idle_exiter_current = NULL;
24 static int                idle_exiters_delete_me = 0;
25
26 /**
27  * @addtogroup Ecore_Group Ecore - Main Loop and Job Functions.
28  *
29  * @{
30  */
31
32 /**
33  * @addtogroup Ecore_Idle_Group Ecore Idle functions
34  *
35  * @{
36  */
37
38 /**
39  * Add an idle exiter handler.
40  * @param func The function to call when exiting an idle state.
41  * @param data The data to be passed to the @p func call
42  * @return A handle to the idle exiter callback on success.  NULL otherwise.
43  */
44 EAPI Ecore_Idle_Exiter *
45 ecore_idle_exiter_add(Ecore_Task_Cb func, const void *data)
46 {
47    Ecore_Idle_Exiter *ie;
48
49    if (!func) return NULL;
50    ie = calloc(1, sizeof(Ecore_Idle_Exiter));
51    if (!ie) return NULL;
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    return ie;
57 }
58
59 /**
60  * Delete an idle exiter handler from the list to be run on exiting idle state.
61  * @param idle_exiter The idle exiter to delete
62  * @return The data pointer that was being being passed to the handler if
63  *         successful.  NULL otherwise.
64  */
65 EAPI void *
66 ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
67 {
68    if (!ECORE_MAGIC_CHECK(idle_exiter, ECORE_MAGIC_IDLE_EXITER))
69      {
70         ECORE_MAGIC_FAIL(idle_exiter, ECORE_MAGIC_IDLE_EXITER,
71                          "ecore_idle_exiter_del");
72         return NULL;
73      }
74    EINA_SAFETY_ON_TRUE_RETURN_VAL(idle_exiter->delete_me, NULL);
75    idle_exiter->delete_me = 1;
76    idle_exiters_delete_me = 1;
77    return idle_exiter->data;
78 }
79
80 /**
81  * @}
82  */
83
84 /**
85  * @}
86  */
87
88 void
89 _ecore_idle_exiter_shutdown(void)
90 {
91    Ecore_Idle_Exiter *ie;
92    while ((ie = idle_exiters))
93      {
94         idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(idle_exiters));
95         ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
96         free(ie);
97      }
98    idle_exiters_delete_me = 0;
99    idle_exiter_current = NULL;
100 }
101
102 void
103 _ecore_idle_exiter_call(void)
104 {
105    if (!idle_exiter_current)
106      {
107         /* regular main loop, start from head */
108         idle_exiter_current = idle_exiters;
109      }
110    else
111      {
112         /* recursive main loop, continue from where we were */
113         idle_exiter_current =
114           (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
115      }
116
117    while (idle_exiter_current)
118      {
119         Ecore_Idle_Exiter *ie = (Ecore_Idle_Exiter *)idle_exiter_current;
120         if (!ie->delete_me)
121           {
122              ie->references++;
123              if (!ie->func(ie->data))
124                {
125                   if (!ie->delete_me) ecore_idle_exiter_del(ie);
126                }
127              ie->references--;
128           }
129         if (idle_exiter_current) /* may have changed in recursive main loops */
130           idle_exiter_current =
131             (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
132      }
133    if (idle_exiters_delete_me)
134      {
135         Ecore_Idle_Exiter *l;
136         int deleted_idler_exiters_in_use = 0;
137
138         for (l = idle_exiters; l;)
139           {
140              Ecore_Idle_Exiter *ie = l;
141
142              l = (Ecore_Idle_Exiter *) EINA_INLIST_GET(l)->next;
143              if (ie->delete_me)
144                {
145                   if (ie->references)
146                     {
147                        deleted_idler_exiters_in_use++;
148                        continue;
149                     }
150
151                   idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
152                   ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
153                   free(ie);
154                }
155           }
156         if (!deleted_idler_exiters_in_use)
157           idle_exiters_delete_me = 0;
158      }
159 }
160
161 int
162 _ecore_idle_exiter_exist(void)
163 {
164    if (idle_exiters) return 1;
165    return 0;
166 }