9 #include "ecore_private.h"
14 static Eina_Bool _ecore_glib_active = EINA_FALSE;
15 static Ecore_Select_Function _ecore_glib_select_original;
16 static GCond *_ecore_glib_cond = NULL;
17 static GPollFD *_ecore_glib_fds = NULL;
18 static size_t _ecore_glib_fds_size = 0;
19 static const size_t ECORE_GLIB_FDS_INITIAL = 128;
20 static const size_t ECORE_GLIB_FDS_STEP = 8;
21 static const size_t ECORE_GLIB_FDS_MAX_FREE = 256;
24 _ecore_glib_fds_resize(size_t size)
26 void *tmp = realloc(_ecore_glib_fds, sizeof(GPollFD) * size);
30 ERR("Could not realloc from %zu to %zu buckets.",
31 _ecore_glib_fds_size, size);
35 _ecore_glib_fds = tmp;
36 _ecore_glib_fds_size = size;
41 _ecore_glib_context_query(GMainContext *ctx,
47 if (_ecore_glib_fds_size == 0)
49 if (!_ecore_glib_fds_resize(ECORE_GLIB_FDS_INITIAL)) return -1;
56 reqfds = g_main_context_query
57 (ctx, priority, p_timer, _ecore_glib_fds, _ecore_glib_fds_size);
58 if (reqfds <= (int)_ecore_glib_fds_size) break;
60 size = (1 + reqfds / ECORE_GLIB_FDS_STEP) * ECORE_GLIB_FDS_STEP;
61 if (!_ecore_glib_fds_resize(size)) return -1;
64 if (reqfds + ECORE_GLIB_FDS_MAX_FREE < _ecore_glib_fds_size)
68 size = (1 + reqfds / ECORE_GLIB_FDS_MAX_FREE) * ECORE_GLIB_FDS_MAX_FREE;
69 _ecore_glib_fds_resize(size);
76 _ecore_glib_context_poll_from(const GPollFD *pfds,
82 const GPollFD *itr = pfds, *itr_end = pfds + count;
85 for (; itr < itr_end; itr++)
87 if (glib_fds < itr->fd)
90 if (itr->events & G_IO_IN)
91 FD_SET(itr->fd, rfds);
92 if (itr->events & G_IO_OUT)
93 FD_SET(itr->fd, wfds);
94 if (itr->events & (G_IO_HUP | G_IO_ERR))
95 FD_SET(itr->fd, efds);
102 _ecore_glib_context_poll_to(GPollFD *pfds,
109 GPollFD *itr = pfds, *itr_end = pfds + count;
111 for (; (itr < itr_end) && (ready > 0); itr++)
114 if (FD_ISSET(itr->fd, rfds) && (itr->events & G_IO_IN))
116 itr->revents |= G_IO_IN;
119 if (FD_ISSET(itr->fd, wfds) && (itr->events & G_IO_OUT))
121 itr->revents |= G_IO_OUT;
124 if (FD_ISSET(itr->fd, efds) && (itr->events & (G_IO_HUP | G_IO_ERR)))
126 itr->revents |= G_IO_ERR;
134 _ecore_glib_select__locked(GMainContext *ctx,
139 struct timeval *ecore_timeout)
141 int priority, maxfds, glib_fds, reqfds, reqtimeout, ret;
142 struct timeval *timeout, glib_timeout;
144 g_main_context_prepare(ctx, &priority);
145 reqfds = _ecore_glib_context_query(ctx, priority, &reqtimeout);
146 if (reqfds < 0) goto error;
148 glib_fds = _ecore_glib_context_poll_from
149 (_ecore_glib_fds, reqfds, rfds, wfds, efds);
151 if (reqtimeout == -1)
152 timeout = ecore_timeout;
155 glib_timeout.tv_sec = reqtimeout / 1000;
156 glib_timeout.tv_usec = (reqtimeout % 1000) * 1000;
158 if (!ecore_timeout || timercmp(ecore_timeout, &glib_timeout, >))
159 timeout = &glib_timeout;
161 timeout = ecore_timeout;
164 maxfds = (ecore_fds >= glib_fds) ? ecore_fds : glib_fds;
165 ret = _ecore_glib_select_original(maxfds, rfds, wfds, efds, timeout);
167 ret = _ecore_glib_context_poll_to
168 (_ecore_glib_fds, reqfds, rfds, wfds, efds, ret);
170 if (g_main_context_check(ctx, priority, _ecore_glib_fds, reqfds))
171 g_main_context_dispatch(ctx);
176 return _ecore_glib_select_original
177 (ecore_fds, rfds, wfds, efds, ecore_timeout);
181 _ecore_glib_select(int ecore_fds,
185 struct timeval *ecore_timeout)
187 GStaticMutex lock = G_STATIC_MUTEX_INIT;
188 GMutex *mutex = g_static_mutex_get_mutex(&lock);
189 GMainContext *ctx = g_main_context_default();
192 if (g_main_context_acquire(ctx))
194 if (mutex) g_mutex_lock(mutex);
198 if (!_ecore_glib_cond)
199 _ecore_glib_cond = g_cond_new();
201 while (!g_main_context_wait(ctx, _ecore_glib_cond, mutex))
205 ret = _ecore_glib_select__locked
206 (ctx, ecore_fds, rfds, wfds, efds, ecore_timeout);
208 if (mutex) g_mutex_unlock(mutex);
209 g_main_context_release(ctx);
210 g_static_mutex_free(&lock);
218 _ecore_glib_init(void)
223 _ecore_glib_shutdown(void)
226 if (!_ecore_glib_active) return;
227 _ecore_glib_active = EINA_FALSE;
229 if (ecore_main_loop_select_func_get() == _ecore_glib_select)
230 ecore_main_loop_select_func_set(_ecore_glib_select_original);
234 free(_ecore_glib_fds);
235 _ecore_glib_fds = NULL;
237 _ecore_glib_fds_size = 0;
239 if (_ecore_glib_cond)
241 g_cond_free(_ecore_glib_cond);
242 _ecore_glib_cond = NULL;
248 * @addtogroup Ecore_Main_Loop_Group
254 * Request ecore to integrate GLib's main loop.
256 * This will add a small overhead during every main loop interaction
257 * by checking glib's default main context (used by its main loop). If
258 * it have events to be checked (timers, file descriptors or idlers),
259 * then these will be polled alongside with Ecore's own events, then
260 * dispatched before Ecore's. This is done by calling
261 * ecore_main_loop_select_func_set().
263 * This will cooperate with previously set
264 * ecore_main_loop_select_func_set() by calling the old
265 * function. Similarly, if you want to override
266 * ecore_main_loop_select_func_set() after main loop is integrated,
267 * call the new select function set by this call (get it by calling
268 * ecore_main_loop_select_func_get() right after
269 * ecore_main_loop_glib_integrate()).
271 * This is useful to use GMainLoop libraries, like GTK, GUPnP,
272 * LibSoup, GConf and more. Adobe Flash plugin and other plugins
273 * systems depend on this as well.
275 * Once initialized/integrated, it will be valid until Ecore is
276 * completely shut down.
284 * ecore_main_loop_glib_integrate();
288 * ecore_main_loop_begin();
297 * @note This is only available if Ecore was compiled with GLib support.
298 * @note You don't need to call this function if Ecore was compiled with
299 * --enable-glib-integration-always.
301 * @return @c EINA_TRUE on success of @c EINA_FALSE if it failed,
302 * likely no GLib support in Ecore.
305 ecore_main_loop_glib_integrate(void)
310 if (_ecore_glib_active) return EINA_TRUE;
311 func = ecore_main_loop_select_func_get();
312 if (func == _ecore_glib_select) return EINA_TRUE;
313 _ecore_glib_select_original = func;
314 ecore_main_loop_select_func_set(_ecore_glib_select);
315 _ecore_glib_active = EINA_TRUE;
318 fputs("ERROR: no glib support in ecore.\n", stderr);
323 Eina_Bool _ecore_glib_always_integrate = 1;
326 * Disable always integrating glib
328 * If ecore is compiled with --enable-glib-integration-always (to always
329 * call ecore_main_loop_glib_integrate() when ecore_init() is called), then
330 * calling this before calling ecore_init() will disable the integration.
331 * This is for apps that explicitly do not want this to happen for whatever
332 * reasons they may have.
335 ecore_main_loop_glib_always_integrate_disable(void)
337 _ecore_glib_always_integrate = 0;