1 /*
2 GSK - a library to write servers
3 Copyright (C) 2001-2004 Dave Benson
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Contact:
20 daveb@ffem.org <Dave Benson>
21 */
22
23 #include <sys/wait.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28
29 #include "gskmainloop.h"
30 #include "gskmacros.h"
31 #include "gskrbtreemacros.h"
32 #include "config.h"
33 #include "gskghelpers.h"
34 #include "gskerrno.h"
35 #include "gskerror.h"
36 #include "gskinit.h"
37 #include "gskdebug.h"
38 #include "cycle.h"
39 #include "debug.h"
40
41 /* --- prototypes --- */
42 static GObjectClass *parent_class = NULL;
43
44 /* lifetime of a source;
45 - created
46 - run (maybe recursively) (maybe repeatedly)
47 - removed from list of sources / io changed
48 - user destroy function run
49 - memory for source free'd
50 */
51
52 /* --- a main-loop source --- */
53 typedef enum
54 {
55 GSK_SOURCE_TYPE_IDLE,
56 GSK_SOURCE_TYPE_TIMER,
57 GSK_SOURCE_TYPE_IO,
58 GSK_SOURCE_TYPE_SIGNAL,
59 GSK_SOURCE_TYPE_PROCESS
60 } GskSourceType;
61
62 struct _GskSource
63 {
64 GskSourceType type;
65 /* are we calling the users' callback? */
66 guint run_count : 16;
67
68 /* is the user's destroy function called? */
69 guint is_destroyed : 1;
70
71 /* was this remove'd while running? */
72 guint must_remove : 1;
73
74 /* are we allowed to recursively invoke this source? */
75 guint is_reentrant : 1;
76
77 /* only for timers */
78 guint timer_adjusted_while_running : 1;
79 guint timer_is_red : 1;
80 guint timer_in_tree : 1;
81
82 GskMainLoop *main_loop;
83
84 gpointer user_data;
85 GDestroyNotify destroy;
86
87 union
88 {
89 struct
90 {
91 int fd;
92 GIOCondition events;
93 GskMainLoopIOFunc func;
94 } io;
95 struct
96 {
97 GTimeVal expire_time;
98 gint64 milli_period;
99 GskMainLoopTimeoutFunc func;
100 GskSource *left, *right, *parent;
101 } timer;
102 struct
103 {
104 int process_id;
105 GskMainLoopWaitPidFunc func;
106 GskSource *prev;
107 GskSource *next;
108 } process;
109 struct
110 {
111 int number;
112 GskMainLoopSignalFunc func;
113 GskSource *prev;
114 GskSource *next;
115 } signal;
116 struct
117 {
118 GskMainLoopIdleFunc func;
119 GskSource *prev;
120 GskSource *next;
121 } idle;
122 } data;
123 };
124
125 struct _GskMainLoopContextList
126 {
127 GMainContext *context;
128 guint num_fds_alloced;
129 GPollFD *poll_fds;
130 GskSource **sources; /* one for each poll_fd */
131 guint num_fds_received;
132 gint priority;
133 GskMainLoopContextList *next;
134 };
135
136 /* --- helper macros --- */
137 #define MAIN_LOOP_CLASS(main_loop) GSK_MAIN_LOOP_GET_CLASS(main_loop)
138 #define DEBUG_POLL(args) \
139 _GSK_DEBUG_PRINTF (GSK_DEBUG_MAIN_LOOP,args)
140
141 /* gskrbtree of timers */
142 #define TIMER_GET_IS_RED(source) ((source)->timer_is_red)
143 #define TIMER_SET_IS_RED(source, v) (source)->timer_is_red=v
144 #define TIMEVALS_COMPARE(a,b) \
145 (a).tv_sec < (b).tv_sec ? -1 \
146 : (a).tv_sec > (b).tv_sec ? +1 \
147 : (a).tv_usec < (b).tv_usec ? -1 \
148 : (a).tv_usec > (b).tv_usec ? +1 \
149 : 0
150 #define TIMER_COMPARE(a,b, rv) \
151 rv = TIMEVALS_COMPARE(a->data.timer.expire_time, b->data.timer.expire_time); \
152 if (rv == 0) { if (a < b) rv = -1; else if (a > b) rv = 1; }
153 #define GET_MAIN_LOOP_TIMER_TREE(main_loop) \
154 (main_loop)->timers, GskSource *, TIMER_GET_IS_RED, TIMER_SET_IS_RED, \
155 data.timer.parent, data.timer.left, data.timer.right, TIMER_COMPARE
156
157
158 static inline GIOCondition
get_io_events(GskMainLoop * main_loop,guint fd)159 get_io_events (GskMainLoop *main_loop,
160 guint fd)
161 {
162 return (main_loop->read_sources->pdata[fd] ? (G_IO_IN|G_IO_HUP) : 0)
163 | (main_loop->write_sources->pdata[fd] ? (G_IO_OUT|G_IO_HUP) : 0);
164 }
165
166 static inline void
gsk_main_loop_change_signal(GskMainLoop * main_loop,guint signal,gboolean add)167 gsk_main_loop_change_signal (GskMainLoop *main_loop,
168 guint signal,
169 gboolean add)
170 {
171 GskMainLoopChange change;
172 change.type = GSK_MAIN_LOOP_EVENT_SIGNAL;
173 change.data.signal.number = signal;
174 change.data.signal.add = add;
175 (*MAIN_LOOP_CLASS (main_loop)->change) (main_loop, &change);
176 DEBUG_POLL (("gsk_main_loop_change_signal: %s watch on signal %d",
177 (add ? "adding" : "removing"), signal));
178 }
179
180 static inline void
gsk_main_loop_change_io(GskMainLoop * main_loop,GIOCondition old_events,guint fd)181 gsk_main_loop_change_io (GskMainLoop *main_loop,
182 GIOCondition old_events,
183 guint fd)
184 {
185 GskMainLoopChange change;
186 change.type = GSK_MAIN_LOOP_EVENT_IO;
187 change.data.io.fd = fd;
188 change.data.io.old_events = old_events;
189 change.data.io.events = get_io_events (main_loop, fd);
190
191 (*MAIN_LOOP_CLASS (main_loop)->change) (main_loop, &change);
192
193 DEBUG_POLL (("gsk_main_loop_change_io: fd=%d: old events:%s%s; "
194 "new events=%s%s",
195 fd,
196 (old_events & G_IO_IN) ? " in" : "",
197 (old_events & G_IO_OUT) ? " out" : "",
198 (change.data.io.events & G_IO_IN) ? " in" : "",
199 (change.data.io.events & G_IO_OUT) ? " out" : ""));
200 }
201
202 static inline void
gsk_main_loop_change_process(GskMainLoop * main_loop,guint pid,gboolean did_exit,gboolean add)203 gsk_main_loop_change_process (GskMainLoop *main_loop,
204 guint pid,
205 gboolean did_exit,
206 gboolean add)
207 {
208 GskMainLoopChange change;
209 if (did_exit)
210 g_assert (!add);
211 change.type = GSK_MAIN_LOOP_EVENT_PROCESS;
212 change.data.process.pid = pid;
213 change.data.process.add = add;
214 change.data.process.did_exit = did_exit;
215 (*MAIN_LOOP_CLASS (main_loop)->change) (main_loop, &change);
216 DEBUG_POLL (("gsk_main_loop_change_process: %s watch on %d",
217 (add ? "adding" : "removing"), pid));
218 }
219
220 static guint
gsk_main_loop_run_io_sources(GskMainLoop * main_loop,guint fd,GIOCondition condition)221 gsk_main_loop_run_io_sources (GskMainLoop *main_loop,
222 guint fd,
223 GIOCondition condition)
224 {
225 GskSource *read_source = NULL;
226 GskSource *write_source = NULL;
227 g_return_val_if_fail (main_loop->read_sources->len > fd, 0);
228 if (condition & G_IO_IN)
229 read_source = main_loop->read_sources->pdata[fd];
230 if (condition & G_IO_OUT)
231 write_source = main_loop->write_sources->pdata[fd];
232 if (read_source == NULL && write_source == NULL)
233 {
234 g_message ("WARNING: got event %u for unknown file-descriptor %d",
235 (guint) condition, fd);
236 return 0;
237 }
238 if (read_source == write_source)
239 {
240 read_source->run_count++;
241 if (!(*read_source->data.io.func) (fd, G_IO_IN | G_IO_OUT,
242 read_source->user_data))
243 read_source->must_remove = 1;
244 read_source->run_count--;
245 if (read_source->run_count == 0 && read_source->must_remove)
246 gsk_source_remove (read_source);
247 return 1;
248 }
249 else
250 {
251 if (read_source != NULL)
252 {
253 read_source->run_count++;
254 if (!(*read_source->data.io.func) (fd, G_IO_IN,
255 read_source->user_data))
256 read_source->must_remove = 1;
257 read_source->run_count--;
258 if (read_source->run_count == 0 && read_source->must_remove)
259 gsk_source_remove (read_source);
260 }
261 if (write_source != NULL)
262 {
263 write_source->run_count++;
264 if (!(*write_source->data.io.func) (fd, G_IO_OUT,
265 write_source->user_data))
266 write_source->must_remove = 1;
267 write_source->run_count--;
268 if (write_source->run_count == 0 && write_source->must_remove)
269 gsk_source_remove (write_source);
270 }
271 return (read_source && write_source) ? 2 : 1;
272 }
273 }
274
275 static guint
gsk_main_loop_run_signal_sources(GskMainLoop * main_loop,guint signal)276 gsk_main_loop_run_signal_sources (GskMainLoop *main_loop,
277 guint signal)
278 {
279 GskSource *at;
280 guint rv = 0;
281 if (main_loop->signal_source_lists->len <= signal)
282 return rv;
283 at = main_loop->signal_source_lists->pdata[signal];
284 if (at != NULL)
285 at->run_count++;
286 while (at != NULL)
287 {
288 GskSource *next;
289 rv++;
290 if (!(*at->data.signal.func) (signal, at->user_data))
291 at->must_remove = 1;
292 next = at->data.signal.next;
293 if (next != NULL)
294 next->run_count++;
295 at->run_count--;
296 if (at->run_count == 0 && at->must_remove)
297 gsk_source_remove (at);
298 at = next;
299 }
300 return rv;
301 }
302
303 static guint
gsk_main_loop_run_process_sources(GskMainLoop * main_loop,GskMainLoopWaitInfo * wait_info)304 gsk_main_loop_run_process_sources (GskMainLoop *main_loop,
305 GskMainLoopWaitInfo *wait_info)
306 {
307 GskSource *at;
308 guint rv = 0;
309
310 g_hash_table_remove (main_loop->alive_pids, GUINT_TO_POINTER (wait_info->pid));
311 at = g_hash_table_lookup (main_loop->process_source_lists,
312 GUINT_TO_POINTER (wait_info->pid));
313 if (at != NULL)
314 at->run_count++;
315 while (at != NULL)
316 {
317 GskSource *next;
318 rv++;
319 (*at->data.process.func) (wait_info, at->user_data);
320 at->must_remove = 1;
321 next = at->data.process.next;
322 if (next != NULL)
323 next->run_count++;
324 at->run_count--;
325 if (at->run_count == 0 && at->must_remove)
326 gsk_source_remove (at);
327 at = next;
328 }
329 return rv;
330 }
331
332 #define INITIAL_MAX_EVENTS 2048
333
334 static inline void
g_time_val_add_millis(GTimeVal * in_out,guint64 millis)335 g_time_val_add_millis (GTimeVal *in_out,
336 guint64 millis)
337 {
338 /* the two cases in this if() statement are
339 equivalent, if millis is really a 32-bit number.
340 but on x86 which lacks good 64-bit divides,
341 the first branch is much faster.
342
343 1<<32 milliseconds is about 50 days,
344 so MOST timeouts are in the first case. */
345
346 /* TODO: we should really decide at compile
347 time if we have fast 64-bit int support,
348 and if so, only use the second branch,
349 to save code space. Of course, i have
350 no idea how to detect it, but it could be based
351 on "cpu".
352
353 TODO: another nice thing would be support for
354 microsecond precision timers. */
355 #ifndef HAVE_FAST_64BIT_INT_SUPPORT /* TODO: define this on non-x86 */
356 if (G_LIKELY ((millis>>32) == 0))
357 {
358 guint ms = (guint) millis;
359 in_out->tv_sec += ms / 1000;
360 in_out->tv_usec += (guint)(ms % 1000) * 1000;
361 }
362 else
363 #endif
364 {
365 in_out->tv_sec += millis / 1000;
366 in_out->tv_usec += (guint)(millis % 1000) * 1000;
367 }
368
369 /* check for overflow of the microseconds column. */
370 if (in_out->tv_usec > 1000 * 1000)
371 {
372 in_out->tv_usec -= 1000 * 1000;
373 in_out->tv_sec++;
374 }
375 }
376
377 #ifdef HAVE_TICK_COUNTER
378 static guint64 last_tick;
379 static GTimeVal last_tick_time;
380 typedef enum
381 {
382 TICK_STATE_INIT,
383 TICK_STATE_HAS_LAST_TICK,
384 TICK_STATE_HAS_TICK_RATE,
385 TICK_STATE_READY,
386 TICK_STATE_FALLBACK
387 } TickState;
388
389 #if defined(TICKS_PER_USEC)
390 static guint usecs_per_tick = USECS_PER_TICK;
391 static guint usecs_per_tick_shift = USECS_PER_TICK_SHIFT;
392 static TickState tick_state = TICK_STATE_HAS_TICK_RATE;
393 static guint64 max_tick_delta = ((1000000ULL * TICKS_PER_USEC_b20) >> 20);
394 #else
395 static guint usecs_per_tick;
396 static guint usecs_per_tick_shift;
397 static TickState tick_state = TICK_STATE_INIT;
398 static guint64 max_tick_delta;
399 #endif
400
401 #if GTIMEVAL_EQUALS_SYS_TIMEVAL
402 #define _gsk_g_get_current_time(tv) gettimeofday((struct timeval*)(tv), NULL)
403 #else
404 #define _gsk_g_get_current_time(tv) g_get_current_time(tv)
405 #endif
406
407 void
gsk_get_current_time(GTimeVal * tv)408 gsk_get_current_time (GTimeVal *tv)
409 {
410 switch (tick_state)
411 {
412 case TICK_STATE_INIT:
413 _gsk_g_get_current_time (&last_tick_time);
414 last_tick = getticks ();
415 *tv = last_tick_time;
416 tick_state = TICK_STATE_HAS_LAST_TICK;
417 break;
418 case TICK_STATE_HAS_LAST_TICK:
419 _gsk_g_get_current_time (tv);
420 if (tv->tv_sec > last_tick_time.tv_sec + 3)
421 {
422 /* compute tick rate */
423 gdouble dusec = ((double)tv->tv_usec - last_tick_time.tv_usec)
424 + 1e6 * ((double)tv->tv_sec - last_tick_time.tv_sec);
425 guint64 this_ticks = getticks ();
426 gint64 dticks = this_ticks - last_tick;
427 gdouble ticks_per_usec_d = (gdouble)dticks / dusec;
428 if (ticks_per_usec_d <= 1.0)
429 {
430 g_message ("ticking too slow... not using cpu timer");
431 tick_state = TICK_STATE_FALLBACK;
432 break;
433 }
434 usecs_per_tick_shift = 30;
435 usecs_per_tick = (double)(1 << usecs_per_tick_shift) / ticks_per_usec_d;
436 max_tick_delta = (guint64)(1000000ULL * ticks_per_usec_d);
437 tick_state = TICK_STATE_READY;
438 if (usecs_per_tick == 0)
439 {
440 g_message ("ticking miscalc");
441 tick_state = TICK_STATE_FALLBACK;
442 break;
443 }
444 last_tick = this_ticks;
445 last_tick_time = *tv;
446 }
447 break;
448 case TICK_STATE_HAS_TICK_RATE:
449 _gsk_g_get_current_time (&last_tick_time);
450 last_tick = getticks ();
451 *tv = last_tick_time;
452 tick_state = TICK_STATE_READY;
453 break;
454 case TICK_STATE_READY:
455 {
456 guint64 this_ticks = getticks ();
457 guint64 delta = this_ticks - last_tick;
458 if (delta > max_tick_delta)
459 {
460 last_tick = this_ticks;
461 _gsk_g_get_current_time (&last_tick_time);
462 *tv = last_tick_time;
463 //g_message ("resync: %u.%06u [ticks=%llu]",(guint)last_tick_time.tv_sec,(guint)last_tick_time.tv_usec,last_tick);
464 }
465 else
466 {
467 guint usecs = (guint)(((guint64)delta * usecs_per_tick) >> usecs_per_tick_shift);
468 //g_message ("delta=%llu; cached time: usecs=%u", delta,usecs);
469 *tv = last_tick_time;
470 tv->tv_usec += usecs;
471 while (tv->tv_usec >= 1000000)
472 {
473 tv->tv_usec -= 1000000;
474 tv->tv_sec += 1;
475 }
476 }
477 break;
478 }
479 case TICK_STATE_FALLBACK:
480 _gsk_g_get_current_time (tv);
481 break;
482
483 default:
484 g_assert_not_reached ();
485 }
486 }
487 #else
488 void
gsk_get_current_time(GTimeVal * tv)489 gsk_get_current_time (GTimeVal *tv)
490 {
491 _gsk_g_get_current_time (tv);
492 }
493 #endif
494
495
496 /**
497 * gsk_main_loop_update_current_time:
498 * @main_loop: main loop whose notion of time should be updated.
499 *
500 * Update the main loop's cached time value by querying the
501 * system clock.
502 */
503 void
gsk_main_loop_update_current_time(GskMainLoop * main_loop)504 gsk_main_loop_update_current_time (GskMainLoop *main_loop)
505 {
506 gsk_get_current_time (&main_loop->current_time);
507 }
508
509 /**
510 * gsk_main_loop_do_waitpid:
511 * @pid: the process id to wait for.
512 * @wait_info: place to collect termination status of the process.
513 *
514 * Do a waitpid system call on the process and munge the
515 * data into @wait_info for the caller to use.
516 *
517 * returns: whether the waitpid succeeded.
518 */
519 gboolean
gsk_main_loop_do_waitpid(int pid,GskMainLoopWaitInfo * wait_info)520 gsk_main_loop_do_waitpid (int pid,
521 GskMainLoopWaitInfo *wait_info)
522 {
523 int status;
524
525 retry:
526 pid = waitpid (pid, &status, WNOHANG);
527 if (pid < 0)
528 {
529 if (gsk_errno_is_ignorable (errno))
530 goto retry;
531
532 /*gsk_log_errno ("error running waitpid");*/
533 return FALSE;
534 }
535 if (pid == 0)
536 return FALSE;
537 wait_info->pid = pid;
538 wait_info->exited = WIFEXITED (status);
539 if (wait_info->exited)
540 {
541 wait_info->d.exit_status = WEXITSTATUS (status);
542 wait_info->dumped_core = FALSE;
543 }
544 else
545 {
546 wait_info->d.signal = WTERMSIG (status);
547 #ifdef WCOREDUMP
548 wait_info->dumped_core = WCOREDUMP (status);
549 #else
550 wait_info->dumped_core = FALSE;
551 #endif
552 }
553 return TRUE;
554 }
555
556
557 static gboolean
handle_poll_fd_set(int fd,GIOCondition condition,gpointer data)558 handle_poll_fd_set (int fd,
559 GIOCondition condition,
560 gpointer data)
561 {
562 GPollFD *poll_fd = data;
563 g_assert (poll_fd->fd == fd);
564 poll_fd->revents = condition;
565 return TRUE;
566 }
567
568 /**
569 * gsk_main_loop_run:
570 * @main_loop: the main loop to run.
571 * @timeout: the maximum number of milliseconds to run, or -1 for no maximum.
572 * @t_waited_out: the number of milliseconds out used, if non-NULL.
573 *
574 * Run the main loop once, for a specified number of milliseconds.
575 *
576 * returns: the number of sources processed.
577 */
578 guint
gsk_main_loop_run(GskMainLoop * main_loop,gint timeout,guint * t_waited_out)579 gsk_main_loop_run (GskMainLoop *main_loop,
580 gint timeout,
581 guint *t_waited_out)
582 {
583 GskMainLoopEvent *events;
584 GskMainLoopClass *class = MAIN_LOOP_CLASS (main_loop);
585 guint num_events;
586 guint rv = 0;
587 GTimeVal old_time;
588 GTimeVal *current_time;
589 guint i;
590 GskSource *at;
591 GskMainLoopContextList *list;
592 GskMainLoopContextList **plist;
593
594 g_return_val_if_fail (!main_loop->is_running, 0);
595 main_loop->is_running = 1;
596
597 gsk_main_loop_update_current_time (main_loop);
598 current_time = &main_loop->current_time;
599 old_time = *current_time;
600 if (main_loop->first_idle != NULL)
601 timeout = 0;
602 GSK_RBTREE_FIRST (GET_MAIN_LOOP_TIMER_TREE (main_loop), at);
603 if (at != NULL)
604 {
605 /* This rounds upward to the nearest millisecond */
606 GTimeVal *exp_time = &at->data.timer.expire_time;
607 if (exp_time->tv_sec < current_time->tv_sec
608 || (exp_time->tv_sec == current_time->tv_sec
609 && exp_time->tv_usec <= current_time->tv_usec))
610 timeout = 0;
611 else
612 {
613 guint ts = exp_time->tv_sec - current_time->tv_sec;
614 gint tus = exp_time->tv_usec - current_time->tv_usec;
615 gint t;
616 if (tus < 0)
617 {
618 tus += 1000000;
619 ts--;
620 }
621 t = ts * 1000 + (tus + 999) / 1000;
622 if (timeout < 0 || t < timeout)
623 timeout = t;
624 }
625 }
626
627 /* TODO: this doesn't work for reentrant main-loops. */
628 events = main_loop->event_array_cache;
629
630 for (plist = &main_loop->first_context; *plist != NULL; )
631 {
632 GskMainLoopContextList *list = *plist;
633 GMainContext *context = list->context;
634 gint c_timeout;
635
636 /* XXX: how can we tell if g_main_loop_quit was called? */
637 #if 0
638 if (context->has_quit)
639 {
640 *plist = list->next;
641 if (*plist == NULL && main_loop->first_context == NULL)
642 main_loop->last_context = NULL;
643
644 g_free (list->poll_fds);
645 g_free (list->sources);
646 g_free (list);
647 continue;
648 }
649 #endif
650
651 if (!g_main_context_prepare (context, &list->priority))
652 {
653 /* i think that TRUE means we can ditch calling 'query';
654 * but we always call query anyways.
655 */
656 }
657
658 /* hmm, is this allowed? */
659 retry_query:
660 list->num_fds_received = g_main_context_query (context, list->priority,
661 &c_timeout,
662 list->poll_fds,
663 list->num_fds_alloced);
664 /* if we filled the entire array, double its size */
665 if (list->num_fds_received == list->num_fds_alloced)
666 {
667 guint new_count = list->num_fds_alloced * 2;
668 list->poll_fds = g_renew (GPollFD, list->poll_fds, new_count);
669 list->sources = g_renew (GskSource *, list->sources, new_count);
670 list->num_fds_alloced = new_count;
671 goto retry_query;
672 }
673
674 if (timeout < 0 || (c_timeout >= 0 && c_timeout < timeout))
675 timeout = c_timeout;
676
677 /* add indication of interest in fd_events/n_events */
678 for (i = 0; i < list->num_fds_received; i++)
679 {
680 GPollFD *poll_fd = &list->poll_fds[i];
681 poll_fd->revents = 0;
682 list->sources[i] = gsk_main_loop_add_io (main_loop,
683 poll_fd->fd,
684 poll_fd->events,
685 handle_poll_fd_set,
686 poll_fd,
687 NULL);
688 }
689 plist = &((*plist)->next);
690 }
691 num_events = (*class->poll) (main_loop, main_loop->max_events, events, timeout);
692 gsk_main_loop_update_current_time (main_loop);
693 /* run i/o, signal and process handlers */
694 for (i = 0; i < num_events; i++)
695 {
696 switch (events[i].type)
697 {
698 case GSK_MAIN_LOOP_EVENT_IO:
699 rv += gsk_main_loop_run_io_sources (main_loop,
700 events[i].data.io.fd,
701 events[i].data.io.events);
702 break;
703 case GSK_MAIN_LOOP_EVENT_SIGNAL:
704 rv += gsk_main_loop_run_signal_sources (main_loop,
705 events[i].data.signal);
706 break;
707 case GSK_MAIN_LOOP_EVENT_PROCESS:
708 rv += gsk_main_loop_run_process_sources (main_loop,
709 &events[i].data.process_wait_info);
710 break;
711 }
712 }
713
714 /* deal with the glib-style main contexts */
715 for (list = main_loop->first_context; list != NULL; list = list->next)
716 {
717 GMainContext *context = list->context;
718 for (i = 0; i < list->num_fds_received; i++)
719 gsk_source_remove (list->sources[i]);
720 g_main_context_check (context, list->priority, list->poll_fds, list->num_fds_received);
721 g_main_context_dispatch (context);
722 }
723
724 /* run idle functions */
725 at = main_loop->first_idle;
726 if (at != NULL)
727 at->run_count++;
728 while (at != NULL)
729 {
730 GskSource *next;
731 if (!(*at->data.idle.func) (at->user_data))
732 at->must_remove = 1;
733 rv++;
734 next = at->data.idle.next;
735 if (next)
736 next->run_count++;
737 at->run_count--;
738 if (at->run_count == 0 && at->must_remove)
739 gsk_source_remove (at);
740 at = next;
741 }
742
743 /* expire timers */
744 for (;;)
745 {
746 GSK_RBTREE_FIRST (GET_MAIN_LOOP_TIMER_TREE (main_loop), at);
747 if (at == NULL)
748 break;
749 if (at->data.timer.expire_time.tv_sec > current_time->tv_sec
750 || (at->data.timer.expire_time.tv_sec == current_time->tv_sec
751 && at->data.timer.expire_time.tv_usec >= current_time->tv_usec))
752 break;
753
754 at->run_count++;
755 g_assert (at->timer_in_tree);
756 GSK_RBTREE_REMOVE (GET_MAIN_LOOP_TIMER_TREE (main_loop), at);
757 at->timer_in_tree = 0;
758 if (!(*at->data.timer.func) (at->user_data))
759 at->must_remove = 1;
760 rv++;
761 at->run_count--;
762 if (at->run_count == 0 && at->must_remove)
763 gsk_source_remove (at);
764 else
765 {
766 if (at->timer_adjusted_while_running)
767 at->timer_adjusted_while_running = 0;
768 else
769 g_time_val_add_millis (&at->data.timer.expire_time,
770 at->data.timer.milli_period);
771 g_assert (!at->timer_in_tree);
772 {
773 GskSource *unused;
774 GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop),
775 at, unused);
776 at->timer_in_tree = 1;
777 }
778 }
779 }
780
781 g_return_val_if_fail (main_loop->is_running, rv);
782 main_loop->is_running = 0;
783
784 if (t_waited_out != NULL)
785 {
786 *t_waited_out = (main_loop->current_time.tv_sec - old_time.tv_sec) * 1000
787 + (main_loop->current_time.tv_usec - old_time.tv_usec) / 1000;
788 }
789
790 if (main_loop->max_events == num_events)
791 {
792 /* If we are pushing the number-of-events threshold,
793 then double the size of our buffer. */
794 main_loop->max_events *= 2;
795 main_loop->event_array_cache
796 = g_renew (GskMainLoopEvent,
797 main_loop->event_array_cache, main_loop->max_events);
798 }
799 return rv;
800 }
801
802 static GMemChunk *gsk_source_chunk = NULL;
803 G_LOCK_DEFINE_STATIC (gsk_source_chunk);
804
805 static inline GskSource *
gsk_source_new(GskSourceType type,GskMainLoop * main_loop,gpointer user_data,GDestroyNotify destroy)806 gsk_source_new (GskSourceType type,
807 GskMainLoop *main_loop,
808 gpointer user_data,
809 GDestroyNotify destroy)
810 {
811 GskSource *rv;
812 G_LOCK (gsk_source_chunk);
813 if (gsk_source_chunk == NULL)
814 gsk_source_chunk = g_mem_chunk_create (GskSource, 16, G_ALLOC_AND_FREE);
815 rv = g_mem_chunk_alloc (gsk_source_chunk);
816 G_UNLOCK (gsk_source_chunk);
817 rv->type = type;
818 rv->user_data = user_data;
819 rv->destroy = destroy;
820 rv->main_loop = main_loop;
821 rv->run_count = 0;
822 rv->must_remove = 0;
823 rv->is_destroyed = 0;
824 rv->is_reentrant = 0;
825 return rv;
826 }
827 static inline void
gsk_source_free(GskSource * gsk_source)828 gsk_source_free (GskSource *gsk_source)
829 {
830 G_LOCK (gsk_source_chunk);
831 g_mem_chunk_free (gsk_source_chunk, gsk_source);
832 G_UNLOCK (gsk_source_chunk);
833 }
834
835 /**
836 * gsk_main_loop_add_idle:
837 * @main_loop: the loop to add the idle function to.
838 * @source_func: the function to call.
839 * @user_data: parameter to be passed to @source_func
840 * @destroy: to be called when the source is destroyed.
841 *
842 * This adds an idle function to the main loop.
843 * An idle function is a function which gets called every
844 * time the main loop is run. Furthermore, while there are
845 * idle functions, the main loop will never block.
846 *
847 * One popular use of idle functions is to defer
848 * an operation, usually because either something is not
849 * in a good state to call immediately,
850 * or because there may be many requests that should
851 * be handled at one time.
852 *
853 * returns: a #GskSource which can be removed (or ignored).
854 */
855 GskSource *
gsk_main_loop_add_idle(GskMainLoop * main_loop,GskMainLoopIdleFunc source_func,gpointer user_data,GDestroyNotify destroy)856 gsk_main_loop_add_idle (GskMainLoop *main_loop,
857 GskMainLoopIdleFunc source_func,
858 gpointer user_data,
859 GDestroyNotify destroy)
860 {
861 GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_IDLE, main_loop, user_data, destroy);
862 source->data.idle.func = source_func;
863 source->data.idle.prev = main_loop->last_idle;
864 source->data.idle.next = NULL;
865 if (main_loop->last_idle == NULL)
866 main_loop->first_idle = source;
867 else
868 main_loop->last_idle->data.idle.next = source;
869 main_loop->last_idle = source;
870 return source;
871 }
872
873 /**
874 * gsk_main_loop_add_signal:
875 * @main_loop: the loop to add the unix signal handler function to.
876 * @signal_number: the number of the signal handler, like SIGINT.
877 * @signal_func: the function to run synchronously when a unix signal is raised.
878 * @user_data: data to be passed to @signal_func.
879 * @destroy: to be called when the source is destroyed.
880 *
881 * Add a signal handler to the main loop.
882 *
883 * Please note that unlike a normal unix signal handler (as provided by
884 * signal(2) or sigaction(2)), this handler will be run synchronously,
885 * so you can call non-reentrant methods.
886 *
887 * Also, because unix signal delivery is unreliable, if the signal is raised a
888 * few times in rapid succession, you may miss some callbacks.
889 *
890 * It is ok to connect multiple times to a single signal simulataneously.
891 *
892 * returns: a #GskSource which can be removed (or ignored).
893 */
894 GskSource *
gsk_main_loop_add_signal(GskMainLoop * main_loop,int signal_number,GskMainLoopSignalFunc signal_func,gpointer user_data,GDestroyNotify destroy)895 gsk_main_loop_add_signal (GskMainLoop *main_loop,
896 int signal_number,
897 GskMainLoopSignalFunc signal_func,
898 gpointer user_data,
899 GDestroyNotify destroy)
900 {
901 GskSource *source;
902 GskSource *first;
903 GskSource *last;
904 //g_return_val_if_fail (signal_number != SIGCHLD, NULL);
905 source = gsk_source_new (GSK_SOURCE_TYPE_SIGNAL, main_loop, user_data, destroy);
906 if (main_loop->signal_source_lists->len <= (guint) signal_number)
907 g_ptr_array_set_size (main_loop->signal_source_lists, signal_number + 1);
908 first = main_loop->signal_source_lists->pdata[signal_number];
909 last = first;
910
911 /* XXX: really need to save last elements!!! */
912 if (last != NULL)
913 while (last->data.signal.next != NULL)
914 last = last->data.signal.next;
915
916 source->data.signal.number = signal_number;
917 source->data.signal.func = signal_func;
918 source->data.signal.prev = last;
919 source->data.signal.next = NULL;
920 if (last == NULL)
921 {
922 gsk_main_loop_change_signal (main_loop, signal_number, TRUE);
923 main_loop->signal_source_lists->pdata[signal_number] = source;
924 }
925 else
926 last->data.signal.next = source;
927 main_loop->num_sources++;
928 return source;
929 }
930
931 /**
932 * gsk_main_loop_add_waitpid:
933 * @main_loop: the loop to add the child-process termination handler function to.
934 * @process_id: the child's process-id to wait for.
935 * @waitpid_func: function to call when the process terminates in some way or another.
936 * @user_data: data to be passed to @waitpid_func
937 * @destroy: to be called when the source is destroyed.
938 *
939 * Add a handler to trap process termination.
940 *
941 * Only one handler is allowed per child process.
942 *
943 * The handler will be invoked synchronously.
944 *
945 * returns: #GskSource which can be removed (or ignored).
946 */
947 GskSource *
gsk_main_loop_add_waitpid(GskMainLoop * main_loop,int process_id,GskMainLoopWaitPidFunc waitpid_func,gpointer user_data,GDestroyNotify destroy)948 gsk_main_loop_add_waitpid (GskMainLoop *main_loop,
949 int process_id,
950 GskMainLoopWaitPidFunc waitpid_func,
951 gpointer user_data,
952 GDestroyNotify destroy)
953 {
954 GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_PROCESS, main_loop, user_data, destroy);
955 GskSource *first;
956 GskSource *last;
957 first = g_hash_table_lookup (main_loop->process_source_lists,
958 GUINT_TO_POINTER (process_id));
959 /* XXX: really need to save last elements!!! */
960 last = first;
961 if (last != NULL)
962 while (last->data.process.next != NULL)
963 last = last->data.process.next;
964 source->data.process.process_id = process_id;
965 source->data.process.prev = last;
966 source->data.process.next = NULL;
967 source->data.process.func = waitpid_func;
968 if (last == NULL)
969 {
970 gsk_main_loop_change_process (main_loop, process_id, FALSE, TRUE);
971 g_hash_table_insert (main_loop->process_source_lists,
972 GUINT_TO_POINTER (process_id),
973 source);
974 }
975 else
976 last->data.process.next = source;
977 main_loop->num_sources++;
978 return source;
979 }
980
981 /**
982 * gsk_main_loop_add_io:
983 * @main_loop: the loop to add the i/o watch to.
984 * @fd: the file-descriptor to watch for events.
985 * @events: initial I/O events to watch for.
986 * @io_func: a function to call when the currently requested
987 * events occur.
988 * @user_data: data to be passed to @io_func
989 * @destroy: to be called when the source is destroyed.
990 *
991 * Add a handler to input or output on a file-descriptor (a socket or a pipe, usually).
992 *
993 * Only one handler trap is allowed per file-descriptor.
994 *
995 * The handler will be re-invoked until the event subsides.
996 * For example, if you read only part of the data when a input event is raised,
997 * the @io_func will be invoked again at every iteration of the main-loop
998 * until there is no data available.
999 *
1000 * returns: a #GskSource which can be removed or altered.
1001 */
1002 GskSource *
gsk_main_loop_add_io(GskMainLoop * main_loop,int fd,guint events,GskMainLoopIOFunc io_func,gpointer user_data,GDestroyNotify destroy)1003 gsk_main_loop_add_io (GskMainLoop *main_loop,
1004 int fd,
1005 guint events,
1006 GskMainLoopIOFunc io_func,
1007 gpointer user_data,
1008 GDestroyNotify destroy)
1009 {
1010 GskSource *source;
1011 GIOCondition old_events;
1012 g_return_val_if_fail (fd >= 0, NULL);
1013 if ((guint) fd >= main_loop->read_sources->len)
1014 {
1015 g_ptr_array_set_size (main_loop->read_sources, fd + 1);
1016 g_ptr_array_set_size (main_loop->write_sources, fd + 1);
1017 }
1018 old_events = get_io_events (main_loop, fd);
1019 g_return_val_if_fail ((old_events & events & (G_IO_IN|G_IO_OUT)) == 0, NULL);
1020 source = gsk_source_new (GSK_SOURCE_TYPE_IO, main_loop, user_data, destroy);
1021 source->data.io.fd = fd;
1022 source->data.io.events = events;
1023 source->data.io.func = io_func;
1024 if ((events & G_IO_IN) == G_IO_IN)
1025 {
1026 g_return_val_if_fail (main_loop->read_sources->pdata[fd] == NULL, NULL);
1027 main_loop->read_sources->pdata[fd] = source;
1028 }
1029 if ((events & G_IO_OUT) == G_IO_OUT)
1030 {
1031 g_return_val_if_fail (main_loop->write_sources->pdata[fd] == NULL, NULL);
1032 main_loop->write_sources->pdata[fd] = source;
1033 }
1034 gsk_main_loop_change_io (main_loop, old_events, fd);
1035 main_loop->num_sources++;
1036 return source;
1037 }
1038
1039 /**
1040 * gsk_source_adjust_io:
1041 * @source: the I/O source which now wants to watch different events.
1042 * @events: the new events to watch for the I/O source.
1043 *
1044 * This changes the types of events being watched by the main-loop.
1045 *
1046 * Note: each new file-descriptor needs a new GskSource.
1047 * You must reuse this GskSource for a new file-descriptor
1048 * even if it happens to have the same numeric value
1049 * as a file-descriptor you closed.
1050 * (The reason why: GSK automatically coagulates
1051 * multiple adjust_io calls. This is fine with all main-loops.
1052 * However, kqueue(2) on BSD, and possibly others, automatically
1053 * unregister all interest in an event if the file-descriptor closes.
1054 * Hence, if the file-descriptor is re-opened and re-used with the
1055 * same GskSource, GSK will not be able to determine
1056 * that anything has changed, and will not issue a new #GskMainLoopChange.
1057 * This will break main-loops that are sensitive to exact which file-descriptor
1058 * (not just the number) was registered.)
1059 */
1060 void
gsk_source_adjust_io(GskSource * source,guint events)1061 gsk_source_adjust_io (GskSource *source,
1062 guint events)
1063 {
1064 guint fd;
1065 GIOCondition old_events;
1066 GskMainLoop *main_loop = source->main_loop;
1067
1068 g_return_if_fail (source != NULL);
1069 g_return_if_fail (source->type == GSK_SOURCE_TYPE_IO);
1070 g_return_if_fail (main_loop->read_sources->len > (guint) source->data.io.fd);
1071
1072 fd = source->data.io.fd;
1073
1074 if ((events & (G_IO_IN|G_IO_OUT)) == (source->data.io.events & (G_IO_IN|G_IO_OUT)))
1075 return;
1076 old_events = get_io_events (main_loop, fd);
1077 if ((events & G_IO_IN) == G_IO_IN)
1078 {
1079 GskSource *old = main_loop->read_sources->pdata[fd];
1080 g_return_if_fail (old == source || old == NULL);
1081 main_loop->read_sources->pdata[fd] = source;
1082 }
1083 else if (main_loop->read_sources->pdata[fd] == source)
1084 main_loop->read_sources->pdata[fd] = NULL;
1085
1086 if ((events & G_IO_OUT) == G_IO_OUT)
1087 {
1088 GskSource *old = main_loop->write_sources->pdata[fd];
1089 g_return_if_fail (old == source || old == NULL);
1090 main_loop->write_sources->pdata[fd] = source;
1091 }
1092 else if (main_loop->write_sources->pdata[fd] == source)
1093 main_loop->write_sources->pdata[fd] = NULL;
1094 source->data.io.events = events;
1095 gsk_main_loop_change_io (main_loop, old_events, fd);
1096 }
1097
1098 /**
1099 * gsk_source_add_io_events:
1100 * @source: the input/output source whose events-of-interest set
1101 * should be expanded.
1102 * @events: new events which should cause @source to wake-up.
1103 *
1104 * Cause this source to be notified if any of the events in
1105 * the @events parameter are set, in addition to the events which
1106 * already caused this source to be woken up.
1107 */
1108 void
gsk_source_add_io_events(GskSource * source,guint events)1109 gsk_source_add_io_events (GskSource *source,
1110 guint events)
1111 {
1112 g_return_if_fail (source != NULL);
1113 g_return_if_fail (source->type == GSK_SOURCE_TYPE_IO);
1114 gsk_source_adjust_io (source, source->data.io.events | events);
1115 }
1116
1117 /**
1118 * gsk_source_remove_io_events:
1119 * @source: the input/output source whose events-of-interest set
1120 * should be reduced.
1121 * @events: new events which should stop causing @source to wake-up.
1122 *
1123 * Cause this source to stop being notified if any of the events in
1124 * the @events parameter are set.
1125 */
1126 void
gsk_source_remove_io_events(GskSource * source,guint events)1127 gsk_source_remove_io_events (GskSource *source,
1128 guint events)
1129 {
1130 g_return_if_fail (source != NULL);
1131 g_return_if_fail (source->type == GSK_SOURCE_TYPE_IO);
1132 gsk_source_adjust_io (source, source->data.io.events & (~events));
1133 }
1134
1135 /**
1136 * gsk_main_loop_add_timer:
1137 * @main_loop: the main-loop which should keep track and run the timeout.
1138 * @timer_func: function to call when the requested amount of time elapses.
1139 * @timer_data: data to pass to @timer_func.
1140 * @timer_destroy: optional function to call to destroy the @timer_data.
1141 * @millis_expire: number of milliseconds to wait before running @timer_func.
1142 * @milli_period: period between subsequent invocation of the timeout.
1143 * This may be -1 to indicate that the timeout is a one-shot.
1144 *
1145 * Add a timeout function to the main-loop.
1146 * This is a function that will be called after
1147 * a fixed amount of time passes, and then may be called
1148 * at a regular interval thereafter.
1149 *
1150 * returns: #GskSource which can be removed or altered.
1151 */
1152 #undef gsk_main_loop_add_timer
1153 GskSource *
gsk_main_loop_add_timer64(GskMainLoop * main_loop,GskMainLoopTimeoutFunc timer_func,gpointer timer_data,GDestroyNotify timer_destroy,gint64 millis_expire,gint64 milli_period)1154 gsk_main_loop_add_timer64 (GskMainLoop *main_loop,
1155 GskMainLoopTimeoutFunc timer_func,
1156 gpointer timer_data,
1157 GDestroyNotify timer_destroy,
1158 gint64 millis_expire,
1159 gint64 milli_period)
1160 {
1161 GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_TIMER, main_loop, timer_data, timer_destroy);
1162 GskSource *unused;
1163 source->data.timer.expire_time = main_loop->current_time;
1164 g_time_val_add_millis (&source->data.timer.expire_time, millis_expire);
1165 source->data.timer.milli_period = milli_period;
1166 source->data.timer.func = timer_func;
1167 source->timer_adjusted_while_running = FALSE;
1168 GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop), source, unused);
1169 source->timer_in_tree = 1;
1170 main_loop->num_sources++;
1171 return source;
1172 }
1173 GskSource *
gsk_main_loop_add_timer(GskMainLoop * main_loop,GskMainLoopTimeoutFunc timer_func,gpointer timer_data,GDestroyNotify timer_destroy,gint millis_expire,gint milli_period)1174 gsk_main_loop_add_timer (GskMainLoop *main_loop,
1175 GskMainLoopTimeoutFunc timer_func,
1176 gpointer timer_data,
1177 GDestroyNotify timer_destroy,
1178 gint millis_expire,
1179 gint milli_period)
1180 {
1181 return gsk_main_loop_add_timer64 (main_loop,
1182 timer_func, timer_data, timer_destroy,
1183 millis_expire, milli_period);
1184 }
1185
1186 /**
1187 * gsk_main_loop_add_timer_absolute:
1188 * @main_loop: the main-loop which should keep track and run the timeout.
1189 * @timer_func: function to call when the requested amount of time elapses.
1190 * @timer_data: data to pass to @timer_func.
1191 * @timer_destroy: optional function to call to destroy the @timer_data.
1192 * @unixtime: number of seconds since Jan 1, 1970 GMT that will have passed when the
1193 * timer should expire.
1194 * @unixtime_micro: fractional part of @unixtime, in microseconds.
1195 *
1196 * Add a timeout function to the main-loop.
1197 * The @timer_func will be called as soon as we detect that the specified time has passed.
1198 *
1199 * The time to wait until is (@unixtime + @unixtime_micro * 10^{-6}) seconds after
1200 * New Years, Jan 1, 1970 GMT.
1201 *
1202 * returns: a #GskSource which can be removed or altered.
1203 */
1204 GskSource *
gsk_main_loop_add_timer_absolute(GskMainLoop * main_loop,GskMainLoopTimeoutFunc timer_func,gpointer timer_data,GDestroyNotify timer_destroy,int unixtime,int unixtime_micro)1205 gsk_main_loop_add_timer_absolute (GskMainLoop *main_loop,
1206 GskMainLoopTimeoutFunc timer_func,
1207 gpointer timer_data,
1208 GDestroyNotify timer_destroy,
1209 int unixtime,
1210 int unixtime_micro)
1211 {
1212 GskSource *source = gsk_source_new (GSK_SOURCE_TYPE_TIMER, main_loop, timer_data, timer_destroy);
1213 GskSource *unused;
1214 source->data.timer.expire_time.tv_sec = unixtime;
1215 source->data.timer.expire_time.tv_usec = unixtime_micro;
1216 source->data.timer.milli_period = -1;
1217 source->data.timer.func = timer_func;
1218 source->timer_adjusted_while_running = 0;
1219 GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop), source, unused);
1220 source->timer_in_tree = 1;
1221 main_loop->num_sources++;
1222 return source;
1223 }
1224
1225 /**
1226 * gsk_source_adjust_timer:
1227 * @timer_source: the timeout source returned by gsk_main_loop_add_timer() or gsk_main_loop_add_timer_absolute().
1228 * @millis_expire: the number of milliseconds from now that the timer should run.
1229 * @milli_period: the period between subsequent runs of the timer, or -1 to indicate that
1230 * the timer is a one-shot.
1231 *
1232 * Adjust the timeout and period for an already existing timer source.
1233 * (You may only call this on timer sources.)
1234 */
1235 #undef gsk_source_adjust_timer /* compatibility hack */
1236 #define gsk_source_adjust_timer gsk_source_adjust_timer64 /* compatibility hack */
1237 void
gsk_source_adjust_timer(GskSource * timer_source,gint64 millis_expire,gint64 milli_period)1238 gsk_source_adjust_timer (GskSource *timer_source,
1239 gint64 millis_expire,
1240 gint64 milli_period)
1241 {
1242 GskMainLoop *main_loop = timer_source->main_loop;
1243 g_return_if_fail (timer_source->type == GSK_SOURCE_TYPE_TIMER);
1244 if (timer_source->timer_in_tree)
1245 {
1246 GSK_RBTREE_REMOVE (GET_MAIN_LOOP_TIMER_TREE (main_loop), timer_source);
1247 timer_source->timer_in_tree = 0;
1248 }
1249 timer_source->data.timer.expire_time = main_loop->current_time;
1250 g_time_val_add_millis (&timer_source->data.timer.expire_time, millis_expire);
1251 timer_source->data.timer.milli_period = milli_period;
1252 if (timer_source->run_count == 0)
1253 {
1254 if (!timer_source->timer_in_tree)
1255 {
1256 GskSource *unused;
1257 GSK_RBTREE_INSERT (GET_MAIN_LOOP_TIMER_TREE (main_loop),
1258 timer_source,
1259 unused);
1260 timer_source->timer_in_tree = 1;
1261 }
1262 }
1263 else
1264 timer_source->timer_adjusted_while_running = 1;
1265 }
1266 #undef gsk_source_adjust_timer /* compatibility hack */
1267 void /* compatibility hack */
gsk_source_adjust_timer(GskSource * timer_source,gint millis_expire,gint milli_period)1268 gsk_source_adjust_timer (GskSource *timer_source,
1269 gint millis_expire,
1270 gint milli_period)
1271 {
1272 gsk_source_adjust_timer64 (timer_source, millis_expire, milli_period);
1273 }
1274
1275 static inline void
gsk_main_loop_block_io(GskMainLoop * main_loop,GskSource * source)1276 gsk_main_loop_block_io (GskMainLoop *main_loop,
1277 GskSource *source)
1278 {
1279 switch (source->type)
1280 {
1281 case GSK_SOURCE_TYPE_IDLE:
1282 if (source->data.idle.prev != NULL)
1283 source->data.idle.prev->data.idle.next = source->data.idle.next;
1284 else
1285 main_loop->first_idle = source->data.idle.next;
1286 if (source->data.idle.next != NULL)
1287 source->data.idle.next->data.idle.prev = source->data.idle.prev;
1288 else
1289 main_loop->last_idle = source->data.idle.prev;
1290 break;
1291
1292 case GSK_SOURCE_TYPE_TIMER:
1293 if (source->timer_in_tree)
1294 {
1295 GSK_RBTREE_REMOVE (GET_MAIN_LOOP_TIMER_TREE (main_loop), source);
1296 source->timer_in_tree = 0;
1297 }
1298 break;
1299
1300 case GSK_SOURCE_TYPE_IO:
1301 {
1302 int fd = source->data.io.fd;
1303 GIOCondition old_events = get_io_events (main_loop, fd);
1304 if ((source->data.io.events & G_IO_IN) == G_IO_IN)
1305 {
1306 g_return_if_fail (main_loop->read_sources->pdata[fd] == source);
1307 main_loop->read_sources->pdata[fd] = NULL;
1308 }
1309 if ((source->data.io.events & G_IO_OUT) == G_IO_OUT)
1310 {
1311 g_return_if_fail (main_loop->write_sources->pdata[fd] == source);
1312 main_loop->write_sources->pdata[fd] = NULL;
1313 }
1314 gsk_main_loop_change_io (main_loop, old_events, fd);
1315 }
1316 break;
1317
1318 case GSK_SOURCE_TYPE_SIGNAL:
1319 {
1320 int signo = source->data.signal.number;
1321 if (source->data.signal.prev != NULL)
1322 source->data.signal.prev->data.signal.next = source->data.signal.next;
1323 else
1324 {
1325 main_loop->signal_source_lists->pdata[signo]
1326 = source->data.signal.next;
1327 if (main_loop->signal_source_lists->pdata[signo] == NULL)
1328 gsk_main_loop_change_signal (main_loop, signo, FALSE);
1329 }
1330 if (source->data.signal.next != NULL)
1331 source->data.signal.next->data.signal.prev = source->data.signal.prev;
1332 break;
1333 }
1334
1335 case GSK_SOURCE_TYPE_PROCESS:
1336 {
1337 guint pid = source->data.process.process_id;
1338 if (source->data.process.prev != NULL)
1339 source->data.process.prev->data.process.next
1340 = source->data.process.next;
1341 else
1342 {
1343 if (source->data.process.next == NULL)
1344 {
1345 g_hash_table_remove (main_loop->process_source_lists,
1346 GUINT_TO_POINTER (pid));
1347 if (g_hash_table_lookup (main_loop->alive_pids,
1348 GUINT_TO_POINTER (pid)))
1349 {
1350 gsk_main_loop_change_process (main_loop, pid, FALSE, FALSE);
1351 g_hash_table_remove (main_loop->alive_pids,
1352 GUINT_TO_POINTER (pid));
1353 }
1354 else
1355 gsk_main_loop_change_process (main_loop, pid, TRUE, FALSE);
1356 }
1357 else
1358 g_hash_table_insert (main_loop->process_source_lists,
1359 GUINT_TO_POINTER (pid),
1360 source->data.process.next);
1361 }
1362 if (source->data.process.next != NULL)
1363 source->data.process.next->data.process.prev
1364 = source->data.process.prev;
1365 break;
1366 }
1367 }
1368 }
1369
1370 /**
1371 * gsk_source_peek_main_loop:
1372 * @source: the source to query.
1373 *
1374 * Get the main-loop where the source was created.
1375 *
1376 * returns: the main-loop associated with the source.
1377 */
gsk_source_peek_main_loop(GskSource * source)1378 GskMainLoop *gsk_source_peek_main_loop (GskSource *source)
1379 {
1380 return source->main_loop;
1381 }
1382
1383 /**
1384 * gsk_source_remove:
1385 * @source: the source to remove and destroy.
1386 *
1387 * Destroy a main loop's source.
1388 *
1389 * If the source is currently running,
1390 * it's destroy method will not be called until the
1391 * source's callback returns. (This way, important data won't be
1392 * deleted unexpectedly in the middle of the user's callback.)
1393 */
1394 void
gsk_source_remove(GskSource * source)1395 gsk_source_remove (GskSource *source)
1396 {
1397 GskMainLoop *main_loop = source->main_loop;
1398 if (source->run_count > 0)
1399 {
1400 /* Remove fd interest immediately, even if reenterring.
1401
1402 This is important because the
1403 caller may be planning to close the file descriptor. */
1404 if (source->type == GSK_SOURCE_TYPE_IO)
1405 {
1406 int fd = source->data.io.fd;
1407 GIOCondition old_events = get_io_events (main_loop, fd);
1408 if (old_events)
1409 {
1410 if (source->data.io.events & G_IO_IN)
1411 main_loop->read_sources->pdata[fd] = NULL;
1412 if (source->data.io.events & G_IO_OUT)
1413 main_loop->write_sources->pdata[fd] = NULL;
1414 source->data.io.events = 0;
1415 gsk_main_loop_change_io (main_loop, old_events, fd);
1416 }
1417 }
1418 source->must_remove = 1;
1419 return;
1420 }
1421
1422 if (!source->is_destroyed)
1423 {
1424 source->is_destroyed = 1;
1425 if (source->destroy != NULL)
1426 (*source->destroy) (source->user_data);
1427 }
1428
1429 /* remove from lists and change i/o handling */
1430 gsk_main_loop_block_io (main_loop, source);
1431 main_loop->num_sources--;
1432
1433 gsk_source_free (source);
1434 }
1435
1436 /**
1437 * gsk_main_loop_quit:
1438 * @main_loop: the main-loop which is being asked to quit.
1439 *
1440 * Set the main-loop flag that indicates that it should really stop running.
1441 *
1442 * If you are executing a GskMainLoop using gsk_main_loop_run(),
1443 * then you should probably check gsk_main_loop_should_continue() at every iteration
1444 * to ensure that you should not have quit by now.
1445 */
1446 void
gsk_main_loop_quit(GskMainLoop * main_loop)1447 gsk_main_loop_quit (GskMainLoop *main_loop)
1448 {
1449 main_loop->quit = 1;
1450 }
1451
1452 /**
1453 * gsk_main_loop_should_continue:
1454 * @main_loop: the main-loop to query.
1455 *
1456 * Query whether the main-loop should keep running or not.
1457 *
1458 * returns: whether to keep running this main-loop.
1459 */
1460 gboolean
gsk_main_loop_should_continue(GskMainLoop * main_loop)1461 gsk_main_loop_should_continue (GskMainLoop *main_loop)
1462 {
1463 #if 0
1464 if (main_loop->quit)
1465 return FALSE;
1466 return main_loop->num_sources > 0 || main_loop->first_context != NULL;
1467 #else
1468 return !main_loop->quit;
1469 #endif
1470 }
1471
1472 /* XXX: this kind of trick should be done constantly (whenever a source
1473 of the appropriate type is removed) */
1474 static void
check_if_all_handlers_clear(GskMainLoop * main_loop)1475 check_if_all_handlers_clear (GskMainLoop *main_loop)
1476 {
1477 guint max_len;
1478 guint i;
1479
1480 /* if all signals are untrapped, reset the array */
1481 max_len = 0;
1482 for (i = 0; i < main_loop->signal_source_lists->len; i++)
1483 if (main_loop->signal_source_lists->pdata[i] != NULL)
1484 max_len = i + 1;
1485 g_ptr_array_set_size (main_loop->signal_source_lists, max_len);
1486
1487 /* if all fds are untrapped, reset the array */
1488 max_len = 0;
1489 for (i = 0; i < main_loop->read_sources->len; i++)
1490 if (main_loop->read_sources->pdata[i] != NULL
1491 || main_loop->write_sources->pdata[i] != NULL)
1492 max_len = i + 1;
1493 g_ptr_array_set_size (main_loop->read_sources, max_len);
1494 g_ptr_array_set_size (main_loop->write_sources, max_len);
1495 }
1496
1497 void
gsk_main_loop_destroy_all_sources(GskMainLoop * main_loop)1498 gsk_main_loop_destroy_all_sources (GskMainLoop *main_loop)
1499 {
1500 /* temporary variables */
1501 GskSource *at;
1502 GSList *list, *at_list;
1503 guint i;
1504
1505 /* Destroy idle functions */
1506 at = main_loop->first_idle;
1507 while (at != NULL)
1508 {
1509 GskSource *next = at->data.idle.next;
1510 if (next != NULL)
1511 next->run_count++;
1512 gsk_source_remove (at);
1513 if (next != NULL)
1514 next->run_count--;
1515
1516 at = next; /* possibly must_remove is set, but it's ok */
1517 }
1518
1519 /* Destroy timers */
1520 while (main_loop->timers)
1521 gsk_source_remove (main_loop->timers);
1522
1523 /* Destroy i/o handlers */
1524 for (i = 0; i < main_loop->read_sources->len; i++)
1525 {
1526 at = main_loop->read_sources->pdata[i];
1527 if (at != NULL)
1528 gsk_source_remove (at);
1529 at = main_loop->write_sources->pdata[i];
1530 if (at != NULL)
1531 gsk_source_remove (at);
1532 }
1533
1534 /* Destroy signal handlers */
1535 for (i = 0; i < main_loop->signal_source_lists->len; i++)
1536 {
1537 at = main_loop->signal_source_lists->pdata[i];
1538 while (at != NULL)
1539 {
1540 GskSource *next = at->data.signal.next;
1541 if (next != NULL)
1542 next->run_count++;
1543 gsk_source_remove (at);
1544 if (next != NULL)
1545 next->run_count--;
1546
1547 at = next; /* possibly must_remove is set, but it's ok */
1548 }
1549 }
1550
1551
1552 /* Destroy waitpid handlers */
1553 list = gsk_g_hash_table_key_slist (main_loop->process_source_lists);
1554 for (at_list = list; at_list != NULL; at_list = at_list->next)
1555 {
1556 at = g_hash_table_lookup (main_loop->process_source_lists, at_list->data);
1557 while (at != NULL)
1558 {
1559 GskSource *next = at->data.idle.next;
1560 if (next != NULL)
1561 next->run_count++;
1562 gsk_source_remove (at);
1563 if (next != NULL)
1564 next->run_count--;
1565
1566 at = next; /* possibly must_remove is set, but it's ok */
1567 }
1568 }
1569 g_slist_free (list);
1570
1571 check_if_all_handlers_clear (main_loop);
1572 }
1573
1574 #define CHECK_INVARIANTS(main_loop) \
1575 G_STMT_START{ \
1576 g_assert (main_loop->write_sources->len == main_loop->read_sources->len); \
1577 }G_STMT_END
1578
1579 static void
gsk_main_loop_finalize(GObject * object)1580 gsk_main_loop_finalize (GObject *object)
1581 {
1582 GskMainLoop *main_loop = GSK_MAIN_LOOP (object);
1583 gsk_main_loop_destroy_all_sources (main_loop);
1584
1585 g_assert (main_loop->first_idle == NULL);
1586 g_assert (main_loop->last_idle == NULL);
1587 g_assert (main_loop->timers == NULL);
1588 g_assert (g_hash_table_size (main_loop->process_source_lists) == 0);
1589 g_assert (main_loop->running_source == NULL);
1590 CHECK_INVARIANTS (main_loop);
1591
1592 g_hash_table_destroy (main_loop->process_source_lists);
1593 g_ptr_array_free (main_loop->read_sources, TRUE);
1594 g_ptr_array_free (main_loop->write_sources, TRUE);
1595 g_ptr_array_free (main_loop->signal_source_lists, TRUE);
1596 g_free (main_loop->event_array_cache);
1597
1598 g_hash_table_destroy (main_loop->alive_pids);
1599
1600 (*parent_class->finalize) (object);
1601 }
1602
1603 /* --- functions --- */
1604 static void
gsk_main_loop_init(GskMainLoop * main_loop)1605 gsk_main_loop_init (GskMainLoop *main_loop)
1606 {
1607 main_loop->timers = NULL;
1608 main_loop->read_sources = g_ptr_array_new ();
1609 main_loop->write_sources = g_ptr_array_new ();
1610 main_loop->signal_source_lists = g_ptr_array_new ();
1611 main_loop->process_source_lists = g_hash_table_new (NULL, NULL);
1612 main_loop->alive_pids = g_hash_table_new (NULL, NULL);
1613 main_loop->max_events = INITIAL_MAX_EVENTS;
1614 main_loop->event_array_cache = g_new (GskMainLoopEvent, main_loop->max_events);
1615 gsk_main_loop_update_current_time (main_loop);
1616 }
1617
1618 static void
gsk_main_loop_class_init(GskMainLoopClass * class)1619 gsk_main_loop_class_init (GskMainLoopClass *class)
1620 {
1621 GObjectClass *object_class = G_OBJECT_CLASS (class);
1622 parent_class = g_type_class_peek_parent (class);
1623 object_class->finalize = gsk_main_loop_finalize;
1624 }
1625
gsk_main_loop_get_type()1626 GType gsk_main_loop_get_type()
1627 {
1628 static GType main_loop_type = 0;
1629 if (!main_loop_type)
1630 {
1631 static const GTypeInfo main_loop_info =
1632 {
1633 sizeof(GskMainLoopClass),
1634 (GBaseInitFunc) NULL,
1635 (GBaseFinalizeFunc) NULL,
1636 (GClassInitFunc) gsk_main_loop_class_init,
1637 NULL, /* class_finalize */
1638 NULL, /* class_data */
1639 sizeof (GskMainLoop),
1640 0, /* n_preallocs */
1641 (GInstanceInitFunc) gsk_main_loop_init,
1642 NULL /* value_table */
1643 };
1644 GType parent = G_TYPE_OBJECT;
1645 main_loop_type = g_type_register_static (parent,
1646 "GskMainLoop",
1647 &main_loop_info, 0);
1648 }
1649 return main_loop_type;
1650 }
1651
1652 /* --- GskMainLoopWaitInfo type registration --- */
1653 static GskMainLoopWaitInfo *
gsk_main_loop_wait_info_copy(const GskMainLoopWaitInfo * wait_info)1654 gsk_main_loop_wait_info_copy (const GskMainLoopWaitInfo *wait_info)
1655 {
1656 return g_memdup (wait_info, sizeof (GskMainLoopWaitInfo));
1657 }
1658
gsk_main_loop_wait_info_get_type(void)1659 GType gsk_main_loop_wait_info_get_type(void)
1660 {
1661 static GType rv = 0;
1662 if (rv == 0)
1663 rv = g_boxed_type_register_static ("GskMainLoopWaitInfo",
1664 (GBoxedCopyFunc) gsk_main_loop_wait_info_copy,
1665 (GBoxedFreeFunc) g_free);
1666 return rv;
1667 }
1668
1669
1670 /* --- Default Construction --- */
1671 #include "main-loops/gskmainloopkqueue.h"
1672 #include "main-loops/gskmainloopdevpoll.h"
1673 #include "main-loops/gskmainloopepoll.h"
1674 #include "main-loops/gskmainlooppoll.h"
1675 #include "main-loops/gskmainloopselect.h"
1676
1677 static struct
1678 {
1679 GType (*get_type_func) () G_GNUC_CONST;
1680 const char *env_value;
1681 gboolean supports_threads;
1682 } main_loop_types[] = {
1683 #if HAVE_EPOLL_SUPPORT
1684 { gsk_main_loop_epoll_get_type, "epoll", TRUE },
1685 #endif
1686 #if HAVE_SYS_DEV_POLL
1687 { gsk_main_loop_dev_poll_get_type, "devpoll", TRUE },
1688 #endif
1689 #if HAVE_KQUEUE
1690 { gsk_main_loop_kqueue_get_type, "kqueue", FALSE },
1691 #endif
1692 #if HAVE_POLL
1693 { gsk_main_loop_poll_get_type, "poll", TRUE },
1694 #endif
1695 #if HAVE_SELECT
1696 { gsk_main_loop_select_get_type, "select", TRUE },
1697 #endif
1698 { NULL, NULL, FALSE }
1699 };
1700
1701
1702 GskMainLoop *
gsk_main_loop_new(GskMainLoopCreateFlags create_flags)1703 gsk_main_loop_new (GskMainLoopCreateFlags create_flags)
1704 {
1705 gboolean threads = (create_flags & GSK_MAIN_LOOP_NEEDS_THREADS) != 0;
1706 GType type = 0;
1707 /* Try the GSK_MAIN_LOOP_TYPE environment variable */
1708 guint i = 0;
1709 const char *env_type = g_getenv ("GSK_MAIN_LOOP_TYPE");
1710
1711 if (env_type != NULL)
1712 {
1713 GSK_SKIP_WHITESPACE (env_type);
1714 if (*env_type == '\0')
1715 env_type = NULL;
1716 }
1717
1718 if (env_type != NULL)
1719 {
1720 GskMainLoop *main_loop;
1721 while (main_loop_types[i].get_type_func != NULL)
1722 {
1723 if (strcmp (env_type, main_loop_types[i].env_value) == 0
1724 && (!threads || main_loop_types[i].supports_threads))
1725 {
1726 type = (*main_loop_types[i].get_type_func) ();
1727 break;
1728 }
1729 i++;
1730 }
1731 if (type == 0)
1732 {
1733 if (strcmp (env_type, "kqueue") == 0)
1734 g_warning ("kqueue doesn't support threads; "
1735 "falling back to poll");
1736 else
1737 g_warning ("GSK_MAIN_LOOP_TYPE set to %s: unsupported", env_type);
1738 }
1739 else
1740 {
1741 GskMainLoopClass *class;
1742 main_loop = g_object_new (type, NULL);
1743 class = GSK_MAIN_LOOP_GET_CLASS (main_loop);
1744 if (class->setup == NULL || (*class->setup) (main_loop))
1745 return main_loop;
1746 else
1747 {
1748 g_warning ("could not setup main-loop of type %s", env_type);
1749 }
1750 g_object_unref (main_loop);
1751 }
1752 }
1753
1754 /* Try autoconf-detected defaults, in our preferred order. */
1755 for (i = 0; main_loop_types[i].get_type_func != NULL; i++)
1756 {
1757 if (!threads || main_loop_types[i].supports_threads)
1758 {
1759 GskMainLoop *main_loop;
1760 GskMainLoopClass *class;
1761 type = (*main_loop_types[i].get_type_func) ();
1762 main_loop = g_object_new (type, NULL);
1763 class = GSK_MAIN_LOOP_GET_CLASS (main_loop);
1764 main_loop->is_setup = 1;
1765 if (class->setup != NULL && !((*class->setup) (main_loop)))
1766 {
1767 g_object_unref (main_loop);
1768 continue;
1769 }
1770 return main_loop;
1771 }
1772 i++;
1773 }
1774
1775 g_warning ("No type of GskMainLoop can be constructed");
1776 return NULL;
1777 }
1778
1779 /* --- GMainLoop support --- */
1780 /**
1781 * gsk_main_loop_add_context:
1782 * @main_loop: main-loop which will take responsibility for @context.
1783 * @context: a GMainContext that should be handled by gsk_main_loop_run().
1784 *
1785 * Indicate that a particular #GskMainLoop will take care of
1786 * invoking the necessary methods of @context.
1787 */
1788 void
gsk_main_loop_add_context(GskMainLoop * main_loop,GMainContext * context)1789 gsk_main_loop_add_context (GskMainLoop *main_loop,
1790 GMainContext *context)
1791 {
1792 GskMainLoopContextList *node = g_new (GskMainLoopContextList, 1);
1793 node->context = context;
1794 node->num_fds_alloced = 16;
1795 node->poll_fds = g_new (GPollFD, node->num_fds_alloced);
1796 node->sources = g_new (GskSource *, node->num_fds_alloced);
1797 node->num_fds_received = 0;
1798 node->priority = G_PRIORITY_DEFAULT;
1799
1800 node->next = NULL;
1801 if (main_loop->last_context != NULL)
1802 main_loop->last_context->next = node;
1803 else
1804 main_loop->first_context = node;
1805 main_loop->last_context = node;
1806 }
1807
1808 /* --- per-thread default main-loop --- */
1809
1810 /* globals for non-threaded main-loops */
1811 static GskMainLoop *non_thread_main_loop = NULL;
1812
1813 /* globals for per-thread main-loops */
1814 static GPrivate *private_main_loop_key;
1815
1816 /**
1817 * gsk_main_loop_default:
1818 *
1819 * Get the main-loop which is associated with the current thread.
1820 *
1821 * returns: a pointer to the main-loop. This function does not
1822 * increase the ref-count on the main-loop, so you do not need
1823 * to call g_object_unref() on the return value.
1824 */
1825 GskMainLoop *
gsk_main_loop_default()1826 gsk_main_loop_default ()
1827 {
1828 if (gsk_init_get_support_threads ())
1829 {
1830 GskMainLoop *main_loop = g_private_get (private_main_loop_key);
1831 if (main_loop != NULL)
1832 return main_loop;
1833 main_loop = gsk_main_loop_new (GSK_MAIN_LOOP_NEEDS_THREADS);
1834 g_assert (main_loop != NULL);
1835 g_private_set (private_main_loop_key, main_loop);
1836 return main_loop;
1837 }
1838 else
1839 {
1840 if (non_thread_main_loop != NULL)
1841 return non_thread_main_loop;
1842 non_thread_main_loop = gsk_main_loop_new (0);
1843 g_assert (non_thread_main_loop != NULL);
1844 return non_thread_main_loop;
1845 }
1846 }
1847
1848 /* --- fork wrapper --- */
1849 void
_gsk_main_loop_fork_notify()1850 _gsk_main_loop_fork_notify ()
1851 {
1852 if (!gsk_init_get_support_threads ())
1853 {
1854 /* NOTE: we don't free the memory for the main-loop,
1855 but it should not amount to much.
1856
1857 However, critical resources that may not be shared,
1858 like file-descriptors should probably be registered
1859 with the gsk_fork_* functions. */
1860
1861 non_thread_main_loop = NULL;
1862 }
1863 }
1864
1865 /* --- initialization --- */
1866 void
_gsk_main_loop_init(void)1867 _gsk_main_loop_init (void)
1868 {
1869 if (gsk_init_get_support_threads ())
1870 private_main_loop_key = g_private_new (g_object_unref);
1871 }
1872