1 /* timer - Delayed and repetitive actions */
3 /* Copyright (c) 2005 Martin Quinson. All rights reserved. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "gras/Msg/msg_private.h"
10 #include "gras/timer.h"
11 #include "gras/Virtu/virtu_interface.h"
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_timer, gras,
15 "Delayed and repetitive actions");
17 /** @brief Request \a action to be called once in \a delay seconds */
18 void gras_timer_delay(double delay, void_f_void_t action)
20 gras_msg_procdata_t pd =
21 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
23 gras_timer_t timer = xbt_dynar_push_ptr(pd->timers);
25 VERB1("Register delayed action %p", action);
26 timer->period = delay;
27 timer->expiry = delay + gras_os_time();
28 timer->action = action;
29 timer->repeat = FALSE;
32 /** @brief Request \a action to be called every \a interval seconds */
33 void gras_timer_repeat(double interval, void_f_void_t action)
35 gras_msg_procdata_t pd =
36 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
38 gras_timer_t timer = xbt_dynar_push_ptr(pd->timers);
40 VERB1("Register repetitive action %p", action);
41 timer->period = interval;
42 timer->expiry = interval + gras_os_time();
43 timer->action = action;
47 /** @brief Cancel a delayed task */
48 void gras_timer_cancel_delay(double interval, void_f_void_t action)
50 gras_msg_procdata_t pd =
51 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
57 xbt_dynar_foreach(pd->timers, cursor, timer) {
58 if (timer.repeat == FALSE &&
59 timer.period == interval && timer.action == action) {
62 xbt_dynar_cursor_rm(pd->timers, &cursor);
67 THROW2(mismatch_error, 0,
68 "Cannot remove the action %p delayed of %f second: not found",
73 /** @brief Cancel a repetitive task */
74 void gras_timer_cancel_repeat(double interval, void_f_void_t action)
76 gras_msg_procdata_t pd =
77 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
83 xbt_dynar_foreach(pd->timers, cursor, timer) {
84 if (timer.repeat == TRUE &&
85 timer.period == interval && timer.action == action) {
88 xbt_dynar_cursor_rm(pd->timers, &cursor);
93 THROW2(mismatch_error, 0,
94 "Cannot remove the action %p delayed of %f second: not found",
98 /** @brief Cancel all delayed tasks */
99 void gras_timer_cancel_delay_all(void)
101 gras_msg_procdata_t pd =
102 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
105 s_gras_timer_t timer;
108 xbt_dynar_foreach(pd->timers, cursor, timer) {
109 if (timer.repeat == FALSE) {
112 xbt_dynar_cursor_rm(pd->timers, &cursor);
117 THROW0(mismatch_error, 0, "No delayed action to remove");
121 /** @brief Cancel all repetitive tasks */
122 void gras_timer_cancel_repeat_all(void)
124 gras_msg_procdata_t pd =
125 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
128 s_gras_timer_t timer;
131 xbt_dynar_foreach(pd->timers, cursor, timer) {
132 if (timer.repeat == FALSE) {
135 xbt_dynar_cursor_rm(pd->timers, &cursor);
140 THROW0(mismatch_error, 0, "No repetitive action to remove");
143 /** @brief Cancel all delayed and repetitive tasks */
144 void gras_timer_cancel_all(void)
146 gras_msg_procdata_t pd =
147 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
148 xbt_dynar_reset(pd->timers);
152 /* returns 0 if it handled a timer, or the delay until next timer, or -1 if no armed timer */
153 double gras_msg_timer_handle(void)
155 gras_msg_procdata_t pd =
156 (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
159 double now = gras_os_time();
160 double untilnext = -1.0;
162 for (cursor = 0; cursor < xbt_dynar_length(pd->timers); cursor++) {
165 timer = xbt_dynar_get_ptr(pd->timers, cursor);
166 untilthis = timer->expiry - now;
168 DEBUG2("Action %p expires in %f", timer->action, untilthis);
170 if (untilthis <= 0.0) {
171 void_f_void_t action = timer->action;
173 DEBUG5("[%.0f] Serve %s action %p (%f<%f)", gras_os_time(),
174 timer->repeat ? "repetitive" : "delayed", timer->action,
178 timer->expiry = now + timer->period;
179 DEBUG4("[%.0f] Re-arm repetitive action %p for %f (period=%f)",
180 gras_os_time(), timer->action, timer->expiry, timer->period);
182 DEBUG2("[%.0f] Remove %p now that it's done", gras_os_time(),
184 xbt_dynar_cursor_rm(pd->timers, &cursor);
188 } else if (untilthis < untilnext || untilnext == -1) {
189 untilnext = untilthis;