Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
b30173511937729255db44d1a33be71f97f5f99a
[simgrid.git] / src / gras / Msg / timer.c
1 /* timer - Delayed and repetitive actions                                   */
2
3 /* Copyright (c) 2005 Martin Quinson. All rights reserved.                  */
4
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. */
7
8 #include "xbt/ex.h"
9 #include "gras/Msg/msg_private.h"
10 #include "gras/timer.h"
11 #include "gras/Virtu/virtu_interface.h"
12
13
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_timer, gras,
15                                 "Delayed and repetitive actions");
16
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)
19 {
20   gras_msg_procdata_t pd =
21     (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
22
23   gras_timer_t timer = xbt_dynar_push_ptr(pd->timers);
24
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;
30 }
31
32 /** @brief Request \a action to be called every \a interval seconds */
33 void gras_timer_repeat(double interval, void_f_void_t action)
34 {
35   gras_msg_procdata_t pd =
36     (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
37
38   gras_timer_t timer = xbt_dynar_push_ptr(pd->timers);
39
40   VERB1("Register repetitive action %p", action);
41   timer->period = interval;
42   timer->expiry = interval + gras_os_time();
43   timer->action = action;
44   timer->repeat = TRUE;
45 }
46
47 /** @brief Cancel a delayed task */
48 void gras_timer_cancel_delay(double interval, void_f_void_t action)
49 {
50   gras_msg_procdata_t pd =
51     (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
52   unsigned int cursor;
53   int found;
54   s_gras_timer_t timer;
55
56   found = FALSE;
57   xbt_dynar_foreach(pd->timers, cursor, timer) {
58     if (timer.repeat == FALSE &&
59         timer.period == interval && timer.action == action) {
60
61       found = TRUE;
62       xbt_dynar_cursor_rm(pd->timers, &cursor);
63     }
64   }
65
66   if (!found)
67     THROW2(mismatch_error, 0,
68            "Cannot remove the action %p delayed of %f second: not found",
69            action, interval);
70
71 }
72
73 /** @brief Cancel a repetitive task */
74 void gras_timer_cancel_repeat(double interval, void_f_void_t action)
75 {
76   gras_msg_procdata_t pd =
77     (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
78   unsigned int cursor;
79   int found;
80   s_gras_timer_t timer;
81
82   found = FALSE;
83   xbt_dynar_foreach(pd->timers, cursor, timer) {
84     if (timer.repeat == TRUE &&
85         timer.period == interval && timer.action == action) {
86
87       found = TRUE;
88       xbt_dynar_cursor_rm(pd->timers, &cursor);
89     }
90   }
91
92   if (!found)
93     THROW2(mismatch_error, 0,
94            "Cannot remove the action %p delayed of %f second: not found",
95            action, interval);
96 }
97
98 /** @brief Cancel all delayed tasks */
99 void gras_timer_cancel_delay_all(void)
100 {
101   gras_msg_procdata_t pd =
102     (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
103   unsigned int cursor;
104   int found;
105   s_gras_timer_t timer;
106
107   found = FALSE;
108   xbt_dynar_foreach(pd->timers, cursor, timer) {
109     if (timer.repeat == FALSE) {
110
111       found = TRUE;
112       xbt_dynar_cursor_rm(pd->timers, &cursor);
113     }
114   }
115
116   if (!found)
117     THROW0(mismatch_error, 0, "No delayed action to remove");
118
119 }
120
121 /** @brief Cancel all repetitive tasks */
122 void gras_timer_cancel_repeat_all(void)
123 {
124   gras_msg_procdata_t pd =
125     (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
126   unsigned int cursor;
127   int found;
128   s_gras_timer_t timer;
129
130   found = FALSE;
131   xbt_dynar_foreach(pd->timers, cursor, timer) {
132     if (timer.repeat == FALSE) {
133
134       found = TRUE;
135       xbt_dynar_cursor_rm(pd->timers, &cursor);
136     }
137   }
138
139   if (!found)
140     THROW0(mismatch_error, 0, "No repetitive action to remove");
141 }
142
143 /** @brief Cancel all delayed and repetitive tasks */
144 void gras_timer_cancel_all(void)
145 {
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);
149 }
150
151
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)
154 {
155   gras_msg_procdata_t pd =
156     (gras_msg_procdata_t) gras_libdata_by_id(gras_msg_libdata_id);
157   unsigned int cursor;
158   gras_timer_t timer;
159   double now = gras_os_time();
160   double untilnext = -1.0;
161
162   for (cursor = 0; cursor < xbt_dynar_length(pd->timers); cursor++) {
163     double untilthis;
164
165     timer = xbt_dynar_get_ptr(pd->timers, cursor);
166     untilthis = timer->expiry - now;
167
168     DEBUG2("Action %p expires in %f", timer->action, untilthis);
169
170     if (untilthis <= 0.0) {
171       void_f_void_t action = timer->action;
172
173       DEBUG5("[%.0f] Serve %s action %p (%f<%f)", gras_os_time(),
174              timer->repeat ? "repetitive" : "delayed", timer->action,
175              timer->expiry, now);
176
177       if (timer->repeat) {
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);
181       } else {
182         DEBUG2("[%.0f] Remove %p now that it's done", gras_os_time(),
183                timer->action);
184         xbt_dynar_cursor_rm(pd->timers, &cursor);
185       }
186       (*action) ();
187       return 0.0;
188     } else if (untilthis < untilnext || untilnext == -1) {
189       untilnext = untilthis;
190     }
191   }
192   return untilnext;
193 }