/** @internal Main loop. * * The function @c su_port_run() waits for wait objects and the timers * associated with the port object. When any wait object is signaled or * timer is expired, it invokes the callbacks, and returns waiting. * * The function @c su_port_run() runs until @c su_port_break() is called * from a callback. * * @param self pointer to port object * */ void su_base_port_run(su_port_t *self) { su_duration_t tout = 0, tout2 = 0; assert(su_port_own_thread(self)); for (self->sup_running = 1; self->sup_running;) { tout = self->sup_max_defer; if (self->sup_prepoll) self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); if (self->sup_head) self->sup_vtable->su_port_getmsgs(self); if (self->sup_timers || self->sup_deferrable) { su_time_t now = su_now(); su_timer_expire(&self->sup_timers, &tout, now); su_timer_expire(&self->sup_deferrable, &tout2, now); } if (!self->sup_running) break; if (self->sup_head) /* if there are messages do a quick wait */ tout = 0; self->sup_vtable->su_port_wait_events(self, tout); } }
static gboolean su_source_dispatch(GSource *gs, GSourceFunc callback, gpointer user_data) { SuSource *ss = (SuSource *)gs; su_port_t *self = ss->ss_port; enter; if (self->sup_base->sup_head) su_base_port_getmsgs(self); if (self->sup_base->sup_timers || self->sup_base->sup_deferrable) { su_time_t now; GTimeVal gtimeval; su_duration_t tout; tout = SU_DURATION_MAX; g_source_get_current_time(gs, >imeval); now.tv_sec = gtimeval.tv_sec + 2208988800UL; now.tv_usec = gtimeval.tv_usec; su_timer_expire(&self->sup_base->sup_timers, &tout, now); su_timer_expire(&self->sup_base->sup_deferrable, &tout, now); } #if SU_HAVE_POLL { su_root_t *root; su_wait_t *waits = self->sup_waits; unsigned i, n = self->sup_n_waits; unsigned version = self->sup_registers; for (i = 0; i < n; i++) { if (waits[i].revents) { root = self->sup_wait_roots[i]; self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, &waits[i], self->sup_wait_args[i]); /* Callback used su_register()/su_unregister() */ if (version != self->sup_registers) break; } } } #endif if (!callback) return TRUE; return callback(user_data); }
/** @internal Block until wait object is signaled or timeout. * * This function waits for wait objects and the timers associated with * the root object. When any wait object is signaled or timer is * expired, it invokes the callbacks. * * This function returns when a callback has been invoked or @c tout * milliseconds is elapsed. * * @param self pointer to port * @param tout timeout in milliseconds * * @return * Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if * there are no active timers. */ su_duration_t su_base_port_step(su_port_t *self, su_duration_t tout) { su_time_t now = su_now(); assert(su_port_own_thread(self)); if (self->sup_prepoll) self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); if (self->sup_head) self->sup_vtable->su_port_getmsgs(self); if (self->sup_timers) su_timer_expire(&self->sup_timers, &tout, now); /* XXX: why isn't the timeout ignored here? */ if (self->sup_deferrable) su_timer_expire(&self->sup_deferrable, &tout, now); /* if there are messages do a quick wait */ if (self->sup_head) tout = 0; if (self->sup_vtable->su_port_wait_events(self, tout)) tout = 0; else tout = SU_WAIT_FOREVER; if (self->sup_head) { if (self->sup_vtable->su_port_getmsgs(self)) { /* Check for wait events that may have been generated by messages */ if (self->sup_vtable->su_port_wait_events(self, 0)) tout = 0; } } if (self->sup_timers || self->sup_deferrable) { su_duration_t tout2 = SU_WAIT_FOREVER; now = su_now(); su_timer_expire(&self->sup_timers, &tout, now); su_timer_expire(&self->sup_deferrable, &tout2, now); if (tout == SU_WAIT_FOREVER && tout2 != SU_WAIT_FOREVER) { if (tout2 < self->sup_max_defer) tout2 = self->sup_max_defer; tout = tout2; } } if (self->sup_head) tout = 0; return tout; }
/* This version can help tuning... */ void su_base_port_run_tune(su_port_t *self) { int i; int timers = 0, messages = 0, events = 0; su_duration_t tout = 0, tout2 = 0; su_time_t started = su_now(), woken = started, bedtime = woken; assert(su_port_own_thread(self)); for (self->sup_running = 1; self->sup_running;) { tout = self->sup_max_defer; timers = 0, messages = 0; if (self->sup_prepoll) self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); if (self->sup_head) messages = self->sup_vtable->su_port_getmsgs(self); if (self->sup_timers || self->sup_deferrable) { su_time_t now = su_now(); timers = su_timer_expire(&self->sup_timers, &tout, now) + su_timer_expire(&self->sup_deferrable, &tout2, now); } if (!self->sup_running) break; if (self->sup_head) /* if there are messages do a quick wait */ tout = 0; bedtime = su_now(); events = self->sup_vtable->su_port_wait_events(self, tout); woken = su_now(); if (messages || timers || events) SU_DEBUG_1(("su_port_run(%p): %.6f: %u messages %u timers %u " "events slept %.6f/%.3f\n", self, su_time_diff(woken, started), messages, timers, events, su_time_diff(woken, bedtime), tout * 1e-3)); if (!self->sup_running) break; } }