2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
12 #include "ecore_private.h"
17 static Eina_Bool _ecore_glib_active = EINA_FALSE;
18 static int (*_ecore_glib_select_original)(int, fd_set*, fd_set*, fd_set*, struct timeval *);
19 static GCond *_ecore_glib_cond = NULL;
20 static GPollFD *_ecore_glib_fds = NULL;
21 static size_t _ecore_glib_fds_size = 0;
22 static const size_t ECORE_GLIB_FDS_INITIAL = 128;
23 static const size_t ECORE_GLIB_FDS_STEP = 8;
24 static const size_t ECORE_GLIB_FDS_MAX_FREE = 256;
27 _ecore_glib_fds_resize(size_t size)
29 void *tmp = realloc(_ecore_glib_fds, sizeof(GPollFD) * size);
32 ERR("Could not realloc from %zu to %zu buckets.",
33 _ecore_glib_fds_size, size);
37 _ecore_glib_fds = tmp;
38 _ecore_glib_fds_size = size;
43 _ecore_glib_context_query(GMainContext *ctx, int priority, int *p_timer)
47 if (_ecore_glib_fds_size == 0)
49 if (!_ecore_glib_fds_resize(ECORE_GLIB_FDS_INITIAL))
57 reqfds = g_main_context_query
58 (ctx, priority, p_timer, _ecore_glib_fds, _ecore_glib_fds_size);
59 if (reqfds <= (int)_ecore_glib_fds_size)
62 size = (1 + reqfds / ECORE_GLIB_FDS_STEP) * ECORE_GLIB_FDS_STEP;
63 if (!_ecore_glib_fds_resize(size))
67 if (reqfds + ECORE_GLIB_FDS_MAX_FREE < _ecore_glib_fds_size)
71 size = (1 + reqfds / ECORE_GLIB_FDS_MAX_FREE) * ECORE_GLIB_FDS_MAX_FREE;
72 _ecore_glib_fds_resize(size);
79 _ecore_glib_context_poll_from(const GPollFD *pfds, int count, fd_set *rfds, fd_set *wfds, fd_set *efds)
81 const GPollFD *itr = pfds, *itr_end = pfds + count;
83 for (; itr < itr_end; itr++)
85 if (glib_fds < itr->fd)
88 if (itr->events & G_IO_IN)
89 FD_SET(itr->fd, rfds);
90 if (itr->events & G_IO_OUT)
91 FD_SET(itr->fd, wfds);
92 if (itr->events & (G_IO_HUP | G_IO_ERR))
93 FD_SET(itr->fd, efds);
100 _ecore_glib_context_poll_to(GPollFD *pfds, int count, const fd_set *rfds, const fd_set *wfds, const fd_set *efds, int ready)
102 GPollFD *itr = pfds, *itr_end = pfds + count;
103 for (; itr < itr_end && ready > 0; itr++)
106 if (FD_ISSET(itr->fd, rfds))
108 itr->revents |= G_IO_IN;
111 if (FD_ISSET(itr->fd, wfds))
113 itr->revents |= G_IO_OUT;
116 if (FD_ISSET(itr->fd, efds))
118 itr->revents |= G_IO_ERR;
126 _ecore_glib_select__locked(GMainContext *ctx, int ecore_fds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *ecore_timeout)
128 int priority, maxfds, glib_fds, reqfds, reqtimeout, ret;
129 struct timeval *timeout, glib_timeout;
131 g_main_context_prepare(ctx, &priority);
132 reqfds = _ecore_glib_context_query(ctx, priority, &reqtimeout);
136 glib_fds = _ecore_glib_context_poll_from
137 (_ecore_glib_fds, reqfds, rfds, wfds, efds);
139 if (reqtimeout == -1)
140 timeout = ecore_timeout;
142 glib_timeout.tv_sec = reqtimeout / 1000;
143 glib_timeout.tv_usec = (reqtimeout % 1000) * 1000;
145 if (!ecore_timeout || timercmp(ecore_timeout, &glib_timeout, >))
146 timeout = &glib_timeout;
148 timeout = ecore_timeout;
151 maxfds = (ecore_fds >= glib_fds) ? ecore_fds : glib_fds;
152 ret = _ecore_glib_select_original(maxfds, rfds, wfds, efds, timeout);
154 ret = _ecore_glib_context_poll_to
155 (_ecore_glib_fds, reqfds, rfds, wfds, efds, ret);
157 if (g_main_context_check(ctx, priority, _ecore_glib_fds, reqfds))
158 g_main_context_dispatch(ctx);
163 return _ecore_glib_select_original
164 (ecore_fds, rfds, wfds, efds, ecore_timeout);
168 _ecore_glib_select(int ecore_fds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *ecore_timeout)
170 GStaticMutex lock = G_STATIC_MUTEX_INIT;
171 GMutex *mutex = g_static_mutex_get_mutex(&lock);
172 GMainContext *ctx = g_main_context_default();
175 if (g_main_context_acquire(ctx))
178 if (!_ecore_glib_cond)
179 _ecore_glib_cond = g_cond_new();
181 while (!g_main_context_wait(ctx, _ecore_glib_cond, mutex))
185 ret = _ecore_glib_select__locked
186 (ctx, ecore_fds, rfds, wfds, efds, ecore_timeout);
188 g_mutex_unlock(mutex);
189 g_main_context_release(ctx);
196 _ecore_glib_init(void)
201 _ecore_glib_shutdown(void)
204 if (!_ecore_glib_active)
206 _ecore_glib_active = EINA_FALSE;
208 if (ecore_main_loop_select_func_get() == _ecore_glib_select)
209 ecore_main_loop_select_func_set(_ecore_glib_select_original);
213 free(_ecore_glib_fds);
214 _ecore_glib_fds = NULL;
216 _ecore_glib_fds_size = 0;
218 if (_ecore_glib_cond)
220 g_cond_free(_ecore_glib_cond);
221 _ecore_glib_cond = NULL;
227 * Request ecore to integrate GLib's main loop.
229 * This will add a small overhead during every main loop interaction
230 * by checking glib's default main context (used by its main loop). If
231 * it have events to be checked (timers, file descriptors or idlers),
232 * then these will be polled alongside with Ecore's own events, then
233 * dispatched before Ecore's. This is done by calling
234 * ecore_main_loop_select_func_set().
236 * This will cooperate with previously set
237 * ecore_main_loop_select_func_set() by calling the old
238 * function. Similarly, if you want to override
239 * ecore_main_loop_select_func_set() after main loop is integrated,
240 * call the new select function set by this call (get it by calling
241 * ecore_main_loop_select_func_get() right after
242 * ecore_main_loop_glib_integrate()).
244 * This is useful to use GMainLoop libraries, like GTK, GUPnP,
245 * LibSoup, GConf and more. Adobe Flash plugin and other plugins
246 * systems depend on this as well.
248 * Once initialized/integrated, it will be valid until Ecore is
249 * completely shut down.
251 * @note this is only available if Ecore was compiled with GLib support.
253 * @return @c EINA_TRUE on success of @c EINA_FALSE if it failed,
254 * likely no GLib support in Ecore.
257 ecore_main_loop_glib_integrate(void)
262 if (_ecore_glib_active)
265 func = ecore_main_loop_select_func_get();
266 if (func == _ecore_glib_select)
268 fputs("ERROR: glib already integrated.\n", stderr);
272 _ecore_glib_select_original = func;
273 ecore_main_loop_select_func_set(_ecore_glib_select);
274 _ecore_glib_active = EINA_TRUE;
277 fputs("ERROR: no glib support in ecore.\n", stderr);