3 /* timer - Delayed and repetitive actions */
5 /* Copyright (c) 2005 Martin Quinson. All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include "gras/Msg/msg_private.h"
12 #include "gras/timer.h"
13 #include "gras/Virtu/virtu_interface.h"
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_timer, gras,
17 "Delayed and repetitive actions");
19 /** @brief Request \a action to be called once in \a delay seconds */
20 void gras_timer_delay(double delay, void_f_void_t action)
22 gras_msg_procdata_t pd =
23 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
25 gras_timer_t timer = xbt_dynar_push_ptr(pd->timers);
27 VERB1("Register delayed action %p", action);
28 timer->period = delay;
29 timer->expiry = delay + gras_os_time();
30 timer->action = action;
31 timer->repeat = FALSE;
34 /** @brief Request \a action to be called every \a interval seconds */
35 void gras_timer_repeat(double interval, void_f_void_t action)
37 gras_msg_procdata_t pd =
38 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
40 gras_timer_t timer = xbt_dynar_push_ptr(pd->timers);
42 VERB1("Register repetitive action %p", action);
43 timer->period = interval;
44 timer->expiry = interval + gras_os_time();
45 timer->action = action;
49 /** @brief Cancel a delayed task */
50 void gras_timer_cancel_delay(double interval, void_f_void_t action)
52 gras_msg_procdata_t pd =
53 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
59 xbt_dynar_foreach(pd->timers, cursor, timer) {
60 if (timer.repeat == FALSE &&
61 timer.period == interval && timer.action == action) {
64 xbt_dynar_cursor_rm(pd->timers, &cursor);
69 THROW2(mismatch_error, 0,
70 "Cannot remove the action %p delayed of %f second: not found",
75 /** @brief Cancel a repetitive task */
76 void gras_timer_cancel_repeat(double interval, void_f_void_t action)
78 gras_msg_procdata_t pd =
79 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
85 xbt_dynar_foreach(pd->timers, cursor, timer) {
86 if (timer.repeat == TRUE &&
87 timer.period == interval && timer.action == action) {
90 xbt_dynar_cursor_rm(pd->timers, &cursor);
95 THROW2(mismatch_error, 0,
96 "Cannot remove the action %p delayed of %f second: not found",
100 /** @brief Cancel all delayed tasks */
101 void gras_timer_cancel_delay_all(void)
103 gras_msg_procdata_t pd =
104 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
107 s_gras_timer_t timer;
110 xbt_dynar_foreach(pd->timers, cursor, timer) {
111 if (timer.repeat == FALSE) {
114 xbt_dynar_cursor_rm(pd->timers, &cursor);
119 THROW0(mismatch_error, 0, "No delayed action to remove");
123 /** @brief Cancel all repetitive tasks */
124 void gras_timer_cancel_repeat_all(void)
126 gras_msg_procdata_t pd =
127 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
130 s_gras_timer_t timer;
133 xbt_dynar_foreach(pd->timers, cursor, timer) {
134 if (timer.repeat == FALSE) {
137 xbt_dynar_cursor_rm(pd->timers, &cursor);
142 THROW0(mismatch_error, 0, "No repetitive action to remove");
145 /** @brief Cancel all delayed and repetitive tasks */
146 void gras_timer_cancel_all(void)
148 gras_msg_procdata_t pd =
149 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
150 xbt_dynar_reset(pd->timers);
154 /* returns 0 if it handled a timer, or the delay until next timer, or -1 if no armed timer */
155 double gras_msg_timer_handle(void)
157 gras_msg_procdata_t pd =
158 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
161 double now = gras_os_time();
162 double untilnext = -1.0;
164 for (cursor = 0; cursor < xbt_dynar_length(pd->timers); cursor++) {
167 timer = xbt_dynar_get_ptr(pd->timers, cursor);
168 untilthis = timer->expiry - now;
170 DEBUG2("Action %p expires in %f", timer->action, untilthis);
172 if (untilthis <= 0.0) {
173 void_f_void_t action = timer->action;
175 DEBUG5("[%.0f] Serve %s action %p (%f<%f)", gras_os_time(),
176 timer->repeat ? "repetitive" : "delayed", timer->action,
180 timer->expiry = now + timer->period;
181 DEBUG4("[%.0f] Re-arm repetitive action %p for %f (period=%f)",
182 gras_os_time(), timer->action, timer->expiry, timer->period);
184 DEBUG2("[%.0f] Remove %p now that it's done", gras_os_time(),
186 xbt_dynar_cursor_rm(pd->timers, &cursor);
190 } else if (untilthis < untilnext || untilnext == -1) {
191 untilnext = untilthis;