1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2007 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
17 TimerManager::TimerManager(InspIRCd* Instance) : CantDeleteHere(false), ServerInstance(Instance)
21 void TimerManager::TickTimers(time_t TIME)
23 this->CantDeleteHere = true;
24 timerlist::iterator found = Timers.find(TIME);
26 if (found != Timers.end())
28 timergroup* x = found->second;
29 /* There are pending timers to trigger.
30 * WARNING: Timers may delete themselves from within
31 * their own Tick methods! see the comment below in
32 * the DelTimer method.
34 for (timergroup::iterator y = x->begin(); y != x->end(); y++)
40 AddTimer(n, n->GetSecs());
52 this->CantDeleteHere = false;
55 void TimerManager::DelTimer(InspTimer* T)
57 if (this->CantDeleteHere)
59 /* If a developer tries to delete a timer from within its own Tick method,
60 * then chances are this is just going to totally fuck over the timergroup
61 * and timerlist iterators and cause a crash. Thanks to peavey and Bricker
62 * for noticing this bug.
63 * If we're within the tick loop when the DelTimer is called (signified
64 * by the var 'CantDeleteHere') then we simply return for non-repeating
65 * timers, and cancel the repeat on repeating timers. We can do this because
66 * we know that the timer tick loop will safely delete the timer for us
67 * anyway and therefore we avoid stack corruption.
75 timerlist::iterator found = Timers.find(T->GetTimer());
77 if (found != Timers.end())
79 timergroup* x = found->second;
80 for (timergroup::iterator y = x->begin(); y != x->end(); y++)
98 /** Because some muppets may do odd things, and their ircd may lock up due
99 * to crappy 3rd party modules, or they may change their system time a bit,
100 * this accounts for shifts of up to 120 secs by looking behind for missed
101 * timers and executing them. This is only executed once every 5 secs.
102 * If you move your clock BACK, and your timers move further ahead as a result,
103 * then tough titty you'll just have to wait.
105 void TimerManager::TickMissedTimers(time_t TIME)
107 for (time_t n = TIME-1; n > TIME-120; n--)
108 this->TickTimers(TIME);
111 void TimerManager::AddTimer(InspTimer* T, long secs_from_now)
113 timergroup* x = NULL;
115 int time_to_trigger = 0;
117 time_to_trigger = T->GetTimer();
119 time_to_trigger = secs_from_now + ServerInstance->Time();
121 timerlist::iterator found = Timers.find(time_to_trigger);
123 if (found != Timers.end())
130 Timers[time_to_trigger] = x;