svn update: 48958 (latest:48959)
[framework/uifw/ecore.git] / src / lib / ecore / ecore_idler.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_Idler
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_Idler *idlers = NULL;
27 static Ecore_Idler *idler_current = NULL;
28 static int          idlers_delete_me = 0;
29
30 /**
31  * Add an idler handler.
32  * @param  func The function to call when idling.
33  * @param  data The data to be passed to this @p func call.
34  * @return A idler handle if successfully added.  NULL otherwise.
35  * @ingroup Idle_Group
36  *
37  * Add an idler handle to the event loop, returning a handle on success and
38  * NULL otherwise.  The function @p func will be called repeatedly while
39  * no other events are ready to be processed, as long as it returns 1
40  * (or ECORE_CALLBACK_RENEW). A return of 0 (or ECORE_CALLBACK_CANCEL) deletes
41  * the idler.
42  *
43  * Idlers are useful for progressively prossessing data without blocking.
44  */
45 EAPI Ecore_Idler *
46 ecore_idler_add(int (*func) (void *data), const void *data)
47 {
48    Ecore_Idler *ie;
49
50    if (!func) return NULL;
51    ie = calloc(1, sizeof(Ecore_Idler));
52    if (!ie) return NULL;
53    ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER);
54    ie->func = func;
55    ie->data = (void *)data;
56    idlers = (Ecore_Idler *) eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
57    return ie;
58 }
59
60 /**
61  * Delete an idler callback from the list to be executed.
62  * @param  idler The handle of the idler callback to delete
63  * @return The data pointer passed to the idler callback on success.  NULL
64  *         otherwise.
65  * @ingroup Idle_Group
66  */
67 EAPI void *
68 ecore_idler_del(Ecore_Idler *idler)
69 {
70    if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER))
71      {
72         ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
73                          "ecore_idler_del");
74         return NULL;
75      }
76    idler->delete_me = 1;
77    idlers_delete_me = 1;
78    return idler->data;
79 }
80
81 void
82 _ecore_idler_shutdown(void)
83 {
84    Ecore_Idler *ie;
85    while ((ie = idlers))
86      {
87         idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(idlers));
88         ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
89         free(ie);
90      }
91    idlers_delete_me = 0;
92    idler_current = NULL;
93 }
94
95 int
96 _ecore_idler_call(void)
97 {
98    if (!idler_current)
99      {
100         /* regular main loop, start from head */
101         idler_current = idlers;
102      }
103    else
104      {
105         /* recursive main loop, continue from where we were */
106         idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
107      }
108
109    while (idler_current)
110      {
111         Ecore_Idler *ie = (Ecore_Idler *)idler_current;
112         if (!ie->delete_me)
113           {
114              ie->references++;
115              if (!ie->func(ie->data)) ecore_idler_del(ie);
116              ie->references--;
117           }
118         if (idler_current) /* may have changed in recursive main loops */
119           idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
120      }
121    if (idlers_delete_me)
122      {
123         Ecore_Idler *l;
124         int deleted_idlers_in_use = 0;
125         for (l = idlers; l;)
126           {
127              Ecore_Idler *ie = l;
128              l = (Ecore_Idler *) EINA_INLIST_GET(l)->next;
129              if (ie->delete_me)
130                {
131                   if (ie->references)
132                     {
133                        deleted_idlers_in_use++;
134                        continue;
135                     }
136
137                   idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
138                   ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
139                   free(ie);
140                }
141           }
142         if (!deleted_idlers_in_use)
143           idlers_delete_me = 0;
144      }
145    if (idlers) return 1;
146    return 0;
147 }
148
149 int
150 _ecore_idler_exist(void)
151 {
152    if (idlers) return 1;
153    return 0;
154 }