timeout.c

Go to the documentation of this file.
00001 /* Routines for time-delayed actions.
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  *
00012  */
00013 
00014 #include "services.h"
00015 #include "pseudo.h"
00016 
00017 static Timeout *timeouts = NULL;
00018 
00019 /*************************************************************************/
00020 
00021 #ifdef DEBUG_COMMANDS
00022 
00023 /* Send the timeout list to the given user. */
00024 
00025 int send_timeout_list(User * u)
00026 {
00027     Timeout *to, *last;
00028 
00029     notice(s_OperServ, u->nick, "Now: %ld", (long int) time(NULL));
00030     for (to = timeouts, last = NULL; to; last = to, to = to->next) {
00031         notice(s_OperServ, u->nick, "0x%p: %ld: 0x%p (0x%p)",
00032                (void *) to, (long int) to->timeout, (void *) to->code,
00033                (void *) to->data);
00034         if (to->prev != last)
00035             notice(s_OperServ, u->nick,
00036                    "    to->prev incorrect!  expected=0x%p seen=0x%p",
00037                    (void *) last, (void *) to->prev);
00038     }
00039     return MOD_CONT;
00040 }
00041 
00042 #endif                          /* DEBUG_COMMANDS */
00043 
00044 /*************************************************************************/
00045 
00046 /* Check the timeout list for any pending actions. */
00047 
00048 void check_timeouts(void)
00049 {
00050     Timeout *to, *to2;
00051     time_t t = time(NULL);
00052 
00053     if (debug >= 2)
00054         alog("debug: Checking timeouts at %ld", (long int) t);
00055 
00056     to = timeouts;
00057     while (to) {
00058         if (t < to->timeout) {
00059             to = to->next;
00060             continue;
00061         }
00062         if (debug >= 4) {
00063             alog("debug: Running timeout 0x%p (code=0x%p repeat=%d)",
00064                  (void *) to, (void *) to->code, to->repeat);
00065         }
00066         to->code(to);
00067         if (to->repeat) {
00068             to = to->next;
00069             continue;
00070         }
00071         to2 = to->next;
00072         if (to->next)
00073             to->next->prev = to->prev;
00074         if (to->prev)
00075             to->prev->next = to->next;
00076         else
00077             timeouts = to->next;
00078         free(to);
00079         to = to2;
00080     }
00081     if (debug >= 2)
00082         alog("debug: Finished timeout list");
00083 }
00084 
00085 /*************************************************************************/
00086 
00087 /* Add a timeout to the list to be triggered in `delay' seconds.  If
00088  * `repeat' is nonzero, do not delete the timeout after it is triggered.
00089  * This must maintain the property that timeouts added from within a
00090  * timeout routine do not get checked during that run of the timeout list.
00091  */
00092 
00093 Timeout *add_timeout(int delay, void (*code) (Timeout *), int repeat)
00094 {
00095     Timeout *t = scalloc(sizeof(Timeout), 1);
00096     t->settime = time(NULL);
00097     t->timeout = t->settime + delay;
00098     t->code = code;
00099     t->repeat = repeat;
00100     t->next = timeouts;
00101     t->prev = NULL;
00102     if (timeouts)
00103         timeouts->prev = t;
00104     timeouts = t;
00105     return t;
00106 }
00107 
00108 /*************************************************************************/
00109 
00110 /* Remove a timeout from the list (if it's there). */
00111 
00112 void del_timeout(Timeout * t)
00113 {
00114     Timeout *ptr;
00115 
00116     for (ptr = timeouts; ptr; ptr = ptr->next) {
00117         if (ptr == t)
00118             break;
00119     }
00120     if (!ptr)
00121         return;
00122     if (t->prev)
00123         t->prev->next = t->next;
00124     else
00125         timeouts = t->next;
00126     if (t->next)
00127         t->next->prev = t->prev;
00128     free(t);
00129 }
00130 
00131 /*************************************************************************/