Commit ce13f1b4 authored by Pekka Pessi's avatar Pekka Pessi

su: added API functions su_timer_is_set() and su_timer_latest()

Re-recorded 20070725161705-65a35-078b884737d9481b0ececff27cdf3a3918ff473b

darcs-hash:20090128180702-db55f-d9dbcf8870efa3f82102947a99c00950e512f8a8.gz
parent 43f9a78f
...@@ -97,8 +97,6 @@ static void su_source_incref(su_port_t *self, char const *who); ...@@ -97,8 +97,6 @@ static void su_source_incref(su_port_t *self, char const *who);
static void su_source_decref(su_port_t *self, int blocking, char const *who); static void su_source_decref(su_port_t *self, int blocking, char const *who);
static struct _GSource *su_source_gsource(su_port_t *port); static struct _GSource *su_source_gsource(su_port_t *port);
static int su_source_send(su_port_t *self, su_msg_r rmsg);
static int su_source_register(su_port_t *self, static int su_source_register(su_port_t *self,
su_root_t *root, su_root_t *root,
su_wait_t *wait, su_wait_t *wait,
...@@ -126,6 +124,8 @@ static int su_source_add_prepoll(su_port_t *port, ...@@ -126,6 +124,8 @@ static int su_source_add_prepoll(su_port_t *port,
static int su_source_remove_prepoll(su_port_t *port, static int su_source_remove_prepoll(su_port_t *port,
su_root_t *root); su_root_t *root);
static int su_source_multishot(su_port_t *self, int multishot); static int su_source_multishot(su_port_t *self, int multishot);
static int su_source_wakeup(su_port_t *self);
static int su_source_is_running(su_port_t *self);
static char const *su_source_name(su_port_t const *self); static char const *su_source_name(su_port_t const *self);
...@@ -141,7 +141,7 @@ su_port_vtable_t const su_source_port_vtable[1] = ...@@ -141,7 +141,7 @@ su_port_vtable_t const su_source_port_vtable[1] =
su_source_gsource, su_source_gsource,
su_source_send, su_base_port_send,
su_source_register, su_source_register,
su_source_unregister, su_source_unregister,
su_source_deregister, su_source_deregister,
...@@ -162,6 +162,10 @@ su_port_vtable_t const su_source_port_vtable[1] = ...@@ -162,6 +162,10 @@ su_port_vtable_t const su_source_port_vtable[1] =
su_base_port_start_shared, su_base_port_start_shared,
su_base_port_wait, su_base_port_wait,
NULL, NULL,
su_base_port_deferrable,
su_base_port_max_defer,
su_source_wakeup,
su_source_is_running,
}}; }};
static char const *su_source_name(su_port_t const *self) static char const *su_source_name(su_port_t const *self)
...@@ -308,37 +312,10 @@ void su_source_finalize(GSource *gs) ...@@ -308,37 +312,10 @@ void su_source_finalize(GSource *gs)
su_source_port_deinit(ss->ss_port); su_source_port_deinit(ss->ss_port);
} }
void su_source_port_lock(su_port_t *self, char const *who)
{
PORT_LOCK_DEBUG(("%p at %s locking(%p)...",
(void *)g_thread_self(), who, self));
g_static_mutex_lock(self->sup_mutex);
PORT_LOCK_DEBUG((" ...%p at %s locked(%p)...",
(void *)g_thread_self(), who, self));
}
void su_source_port_unlock(su_port_t *self, char const *who)
{
g_static_mutex_unlock(self->sup_mutex);
PORT_LOCK_DEBUG((" ...%p at %s unlocked(%p)\n",
(void *)g_thread_self(), who, self));
}
/** @internal Send a message to the port. */ /** @internal Send a message to the port. */
int su_source_send(su_port_t *self, su_msg_r rmsg) int su_source_wakeup(su_port_t *self)
{ {
int wakeup = su_base_port_send(self, rmsg); GMainContext *gmc = g_source_get_context(self->sup_source);
GMainContext *gmc;
if (wakeup < 0)
return -1;
if (wakeup == 0)
return 0;
gmc = g_source_get_context(self->sup_source);
if (gmc) if (gmc)
g_main_context_wakeup(gmc); g_main_context_wakeup(gmc);
...@@ -837,7 +814,7 @@ int su_source_deregister(su_port_t *self, int i) ...@@ -837,7 +814,7 @@ int su_source_deregister(su_port_t *self, int i)
* @return Number of wait objects removed. * @return Number of wait objects removed.
*/ */
int su_source_unregister_all(su_port_t *self, int su_source_unregister_all(su_port_t *self,
su_root_t *root) su_root_t *root)
{ {
unsigned i, j; unsigned i, j;
unsigned n_waits; unsigned n_waits;
...@@ -881,8 +858,7 @@ int su_source_unregister_all(su_port_t *self, ...@@ -881,8 +858,7 @@ int su_source_unregister_all(su_port_t *self,
/**Set mask for a registered event. @internal /**Set mask for a registered event. @internal
* *
* The function su_source_eventmask() sets the mask describing events that can * Sets the mask describing events that can signal the registered callback.
* signal the registered callback.
* *
* @param port pointer to port object * @param port pointer to port object
* @param index registration index * @param index registration index
...@@ -892,6 +868,7 @@ int su_source_unregister_all(su_port_t *self, ...@@ -892,6 +868,7 @@ int su_source_unregister_all(su_port_t *self,
* @retval 0 when successful, * @retval 0 when successful,
* @retval -1 upon an error. * @retval -1 upon an error.
*/ */
static
int su_source_eventmask(su_port_t *self, int index, int socket, int events) int su_source_eventmask(su_port_t *self, int index, int socket, int events)
{ {
unsigned n; unsigned n;
...@@ -932,15 +909,13 @@ int su_source_multishot(su_port_t *self, int multishot) ...@@ -932,15 +909,13 @@ int su_source_multishot(su_port_t *self, int multishot)
} }
/** @internal Main loop. /** @internal Run the main loop.
*
* The function @c su_source_run() runs the main loop
* *
* The function @c su_source_run() runs until @c su_source_break() is called * The main loop runs until su_source_break() is called from a callback.
* from a callback.
* *
* @param self pointer to root object * @param self pointer to port object
* */ * */
static
void su_source_run(su_port_t *self) void su_source_run(su_port_t *self)
{ {
GMainContext *gmc; GMainContext *gmc;
...@@ -959,6 +934,11 @@ void su_source_run(su_port_t *self) ...@@ -959,6 +934,11 @@ void su_source_run(su_port_t *self)
} }
} }
static int su_source_is_running(su_port_t *self)
{
return self->sup_main_loop && g_main_loop_is_running(self->sup_main_loop);
}
/** @internal /** @internal
* The function @c su_source_break() is used to terminate execution of @c * The function @c su_source_break() is used to terminate execution of @c
* su_source_run(). It can be called from a callback function. * su_source_run(). It can be called from a callback function.
...@@ -966,6 +946,7 @@ void su_source_run(su_port_t *self) ...@@ -966,6 +946,7 @@ void su_source_run(su_port_t *self)
* @param self pointer to port * @param self pointer to port
* *
*/ */
static
void su_source_break(su_port_t *self) void su_source_break(su_port_t *self)
{ {
enter; enter;
...@@ -1112,4 +1093,3 @@ void su_glib_prefer_gsource(void) ...@@ -1112,4 +1093,3 @@ void su_glib_prefer_gsource(void)
{ {
su_port_prefer(su_source_port_create, NULL); su_port_prefer(su_source_port_create, NULL);
} }
...@@ -491,6 +491,8 @@ SOFIAPUBFUN su_duration_t su_root_get_max_defer(su_root_t const *self); ...@@ -491,6 +491,8 @@ SOFIAPUBFUN su_duration_t su_root_get_max_defer(su_root_t const *self);
SOFIAPUBFUN su_timer_t *su_timer_create(su_task_r const, su_duration_t msec) SOFIAPUBFUN su_timer_t *su_timer_create(su_task_r const, su_duration_t msec)
__attribute__((__malloc__)); __attribute__((__malloc__));
SOFIAPUBFUN void su_timer_destroy(su_timer_t *); SOFIAPUBFUN void su_timer_destroy(su_timer_t *);
SOFIAPUBFUN int su_timer_is_set(su_timer_t const *t); /* 1.12.11 */
SOFIAPUBFUN su_time_t su_timer_latest(su_timer_t const *t);
SOFIAPUBFUN int su_timer_set(su_timer_t *, su_timer_f, su_timer_arg_t *); SOFIAPUBFUN int su_timer_set(su_timer_t *, su_timer_f, su_timer_arg_t *);
SOFIAPUBFUN int su_timer_set_interval(su_timer_t *t, su_timer_f, SOFIAPUBFUN int su_timer_set_interval(su_timer_t *t, su_timer_f,
su_timer_arg_t *, su_duration_t); su_timer_arg_t *, su_duration_t);
...@@ -506,7 +508,7 @@ SOFIAPUBFUN su_root_t *su_timer_root(su_timer_t const *); ...@@ -506,7 +508,7 @@ SOFIAPUBFUN su_root_t *su_timer_root(su_timer_t const *);
SOFIAPUBFUN int su_timer_expire(su_timer_queue_t * const, SOFIAPUBFUN int su_timer_expire(su_timer_queue_t * const,
su_duration_t *tout, su_duration_t *tout,
su_time_t now); su_time_t now);
SOFIAPUBFUN int su_timer_deferrable(su_timer_t *t, int value); SOFIAPUBFUN int su_timer_deferrable(su_timer_t *t, int value); /* 1.12.11 */
/* Tasks */ /* Tasks */
......
...@@ -157,12 +157,11 @@ typedef union { ...@@ -157,12 +157,11 @@ typedef union {
struct su_timer_s { struct su_timer_s {
su_task_r sut_task; /**< Task reference */ su_task_r sut_task; /**< Task reference */
size_t sut_heap_index; /**< Timer is set (inserted in heap) */ size_t sut_set; /**< Timer is set (inserted in heap) */
su_time_t sut_when; /**< When timer should be waken up next time */ su_time_t sut_when; /**< When timer should be waken up next time */
su_duration_t sut_duration; /**< Timer duration */ su_duration_t sut_duration; /**< Timer duration */
su_timer_f sut_wakeup; /**< Function to call when waken up */ su_timer_f sut_wakeup; /**< Function to call when waken up */
su_timer_arg_t *sut_arg; /**< Pointer to argument data */ su_timer_arg_t *sut_arg; /**< Pointer to argument data */
su_time_t sut_run; /**< When this timer was last waken up */
unsigned sut_woken; /**< Timer has waken up this many times */ unsigned sut_woken; /**< Timer has waken up this many times */
unsigned sut_running:2;/**< Timer is running */ unsigned sut_running:2;/**< Timer is running */
...@@ -176,13 +175,13 @@ enum sut_running { ...@@ -176,13 +175,13 @@ enum sut_running {
run_for_ever = 2 /**< Do not compensate */ run_for_ever = 2 /**< Do not compensate */
}; };
#define SU_TIMER_IS_SET(sut) ((sut)->sut_heap_index != 0) #define SU_TIMER_IS_SET(sut) ((sut)->sut_set != 0)
HEAP_DECLARE(su_inline, su_timer_queue_t, timers_, su_timer_t *); HEAP_DECLARE(su_inline, su_timer_queue_t, timers_, su_timer_t *);
su_inline void timers_set(su_timer_t **array, size_t index, su_timer_t *t) su_inline void timers_set(su_timer_t **array, size_t index, su_timer_t *t)
{ {
array[t->sut_heap_index = index] = t; array[t->sut_set = index] = t;
} }
su_inline int timers_less(su_timer_t *a, su_timer_t *b) su_inline int timers_less(su_timer_t *a, su_timer_t *b)
...@@ -224,7 +223,7 @@ su_timer_set0(su_timer_queue_t *timers, ...@@ -224,7 +223,7 @@ su_timer_set0(su_timer_queue_t *timers,
return -1; return -1;
if (SU_TIMER_IS_SET(t)) if (SU_TIMER_IS_SET(t))
timers_remove(timers[0], t->sut_heap_index); timers_remove(timers[0], t->sut_set);
t->sut_wakeup = wakeup; t->sut_wakeup = wakeup;
t->sut_arg = arg; t->sut_arg = arg;
...@@ -328,6 +327,37 @@ void su_timer_destroy(su_timer_t *t) ...@@ -328,6 +327,37 @@ void su_timer_destroy(su_timer_t *t)
} }
} }
/** Check if the timer has been set.
*
* @param t pointer to a timer object
*
* @return Nonzero if set, zero if reset.
*
* @NEW_1_12_11
*/
int su_timer_is_set(su_timer_t const *t)
{
return t && t->sut_set != 0;
}
/**Return when the timer has been last expired.
*
* @param t pointer to a timer object
*
* @return Timestamp (as returned by su_time()).
*
* @note If the timer is running (set with su_timer_run()), the returned
* timestamp not the actual time but it is rather calculated from the
* initial timestamp.
*
* @NEW_1_12_11
*/
su_time_t su_timer_latest(su_timer_t const *t)
{
su_time_t tv = { 0, 0 };
return t ? t->sut_when : tv;
}
/** Set the timer for the given @a interval. /** Set the timer for the given @a interval.
* *
...@@ -415,16 +445,14 @@ int su_timer_run(su_timer_t *t, ...@@ -415,16 +445,14 @@ int su_timer_run(su_timer_t *t,
su_timer_arg_t *arg) su_timer_arg_t *arg)
{ {
su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_run"); su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_run");
su_time_t now;
if (timers == NULL) if (timers == NULL)
return -1; return -1;
t->sut_running = run_at_intervals; t->sut_running = run_at_intervals;
t->sut_run = now = su_now();
t->sut_woken = 0; t->sut_woken = 0;
return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration); return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
} }
/**Set the timer for regular intervals. /**Set the timer for regular intervals.
...@@ -448,16 +476,14 @@ int su_timer_set_for_ever(su_timer_t *t, ...@@ -448,16 +476,14 @@ int su_timer_set_for_ever(su_timer_t *t,
su_timer_arg_t *arg) su_timer_arg_t *arg)
{ {
su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_set_for_ever"); su_timer_queue_t *timers = su_timer_queue(t, 1, "su_timer_set_for_ever");
su_time_t now;
if (timers == NULL) if (timers == NULL)
return -1; return -1;
t->sut_running = run_for_ever; t->sut_running = run_for_ever;
t->sut_run = now = su_now();
t->sut_woken = 0; t->sut_woken = 0;
return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration); return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
} }
/**Reset the timer. /**Reset the timer.
...@@ -476,14 +502,12 @@ int su_timer_reset(su_timer_t *t) ...@@ -476,14 +502,12 @@ int su_timer_reset(su_timer_t *t)
return -1; return -1;
if (SU_TIMER_IS_SET(t)) if (SU_TIMER_IS_SET(t))
timers_remove(timers[0], t->sut_heap_index); timers_remove(timers[0], t->sut_set);
t->sut_wakeup = NULL; t->sut_wakeup = NULL;
t->sut_arg = NULL; t->sut_arg = NULL;
t->sut_running = reset; t->sut_running = reset;
memset(&t->sut_run, 0, sizeof(t->sut_run));
return 0; return 0;
} }
...@@ -528,12 +552,13 @@ int su_timer_expire(su_timer_queue_t * const timers, ...@@ -528,12 +552,13 @@ int su_timer_expire(su_timer_queue_t * const timers,
if (t->sut_running == run_at_intervals) { if (t->sut_running == run_at_intervals) {
while (t->sut_running == run_at_intervals && while (t->sut_running == run_at_intervals &&
t->sut_set == 0 &&
t->sut_duration > 0) { t->sut_duration > 0) {
if (su_time_diff(t->sut_when, now) > 0) { if (su_time_diff(t->sut_when, now) > 0) {
su_timer_set0(timers, t, f, t->sut_arg, t->sut_run, 0); su_timer_set0(timers, t, f, t->sut_arg, t->sut_when, 0);
break; break;
} }
t->sut_when = t->sut_run = su_time_add(t->sut_run, t->sut_duration); t->sut_when = su_time_add(t->sut_when, t->sut_duration);
t->sut_woken++; t->sut_woken++;
f(su_root_magic(su_task_root(t->sut_task)), t, t->sut_arg), n++; f(su_root_magic(su_task_root(t->sut_task)), t, t->sut_arg), n++;
} }
...@@ -542,7 +567,7 @@ int su_timer_expire(su_timer_queue_t * const timers, ...@@ -542,7 +567,7 @@ int su_timer_expire(su_timer_queue_t * const timers,
t->sut_woken++; t->sut_woken++;
t->sut_when = now; t->sut_when = now;
f(su_root_magic(su_task_root(t->sut_task)), t, t->sut_arg), n++; f(su_root_magic(su_task_root(t->sut_task)), t, t->sut_arg), n++;
if (t->sut_running == run_for_ever) if (t->sut_running == run_for_ever && t->sut_set == 0)
su_timer_set0(timers, t, f, t->sut_arg, now, t->sut_duration); su_timer_set0(timers, t, f, t->sut_arg, now, t->sut_duration);
} }
else { else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment