svn update: 48958 (latest:48959)
[framework/uifw/ecore.git] / src / lib / ecore / ecore_idle_exiter.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <stdlib.h>
10
11 #include "Ecore.h"
12 #include "ecore_private.h"
13
14
15 struct _Ecore_Idle_Exiter
16 {
17    EINA_INLIST;
18    ECORE_MAGIC;
19    int        (*func) (void *data);
20    void        *data;
21    int          references;
22    Eina_Bool    delete_me : 1;
23 };
24
25
26 static Ecore_Idle_Exiter *idle_exiters = NULL;
27 static Ecore_Idle_Exiter *idle_exiter_current = NULL;
28 static int                idle_exiters_delete_me = 0;
29
30 /**
31  * Add an idle exiter handler.
32  * @param func The function to call when exiting an idle state.
33  * @param data The data to be passed to the @p func call
34  * @return A handle to the idle exiter callback on success.  NULL otherwise.
35  * @ingroup Idle_Group
36  */
37 EAPI Ecore_Idle_Exiter *
38 ecore_idle_exiter_add(int (*func) (void *data), const void *data)
39 {
40    Ecore_Idle_Exiter *ie;
41
42    if (!func) return NULL;
43    ie = calloc(1, sizeof(Ecore_Idle_Exiter));
44    if (!ie) return NULL;
45    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_EXITER);
46    ie->func = func;
47    ie->data = (void *)data;
48    idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_append(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
49    return ie;
50 }
51
52 /**
53  * Delete an idle exiter handler from the list to be run on exiting idle state.
54  * @param idle_exiter The idle exiter to delete
55  * @return The data pointer that was being being passed to the handler if
56  *         successful.  NULL otherwise.
57  * @ingroup Idle_Group
58  */
59 EAPI void *
60 ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
61 {
62    if (!ECORE_MAGIC_CHECK(idle_exiter, ECORE_MAGIC_IDLE_EXITER))
63      {
64         ECORE_MAGIC_FAIL(idle_exiter, ECORE_MAGIC_IDLE_EXITER,
65                          "ecore_idle_exiter_del");
66         return NULL;
67      }
68    idle_exiter->delete_me = 1;
69    idle_exiters_delete_me = 1;
70    return idle_exiter->data;
71 }
72
73 void
74 _ecore_idle_exiter_shutdown(void)
75 {
76    Ecore_Idle_Exiter *ie;
77    while ((ie = idle_exiters))
78      {
79         idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(idle_exiters));
80         ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
81         free(ie);
82      }
83    idle_exiters_delete_me = 0;
84    idle_exiter_current = NULL;
85 }
86
87 void
88 _ecore_idle_exiter_call(void)
89 {
90    if (!idle_exiter_current)
91      {
92         /* regular main loop, start from head */
93         idle_exiter_current = idle_exiters;
94      }
95    else
96      {
97         /* recursive main loop, continue from where we were */
98         idle_exiter_current =
99           (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
100      }
101
102    while (idle_exiter_current)
103      {
104         Ecore_Idle_Exiter *ie = (Ecore_Idle_Exiter *)idle_exiter_current;
105         if (!ie->delete_me)
106           {
107              ie->references++;
108              if (!ie->func(ie->data)) ecore_idle_exiter_del(ie);
109              ie->references--;
110           }
111         if (idle_exiter_current) /* may have changed in recursive main loops */
112           idle_exiter_current =
113             (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
114      }
115    if (idle_exiters_delete_me)
116      {
117         Ecore_Idle_Exiter *l;
118         int deleted_idler_exiters_in_use = 0;
119
120         for (l = idle_exiters; l;)
121           {
122              Ecore_Idle_Exiter *ie = l;
123
124              l = (Ecore_Idle_Exiter *) EINA_INLIST_GET(l)->next;
125              if (ie->delete_me)
126                {
127                   if (ie->references)
128                     {
129                        deleted_idler_exiters_in_use++;
130                        continue;
131                     }
132
133                   idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
134                   ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
135                   free(ie);
136                }
137           }
138         if (!deleted_idler_exiters_in_use)
139           idle_exiters_delete_me = 0;
140      }
141 }
142
143 int
144 _ecore_idle_exiter_exist(void)
145 {
146    if (idle_exiters) return 1;
147    return 0;
148 }