Logo AND Algorithmique Numérique Distribuée

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