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 * ---------------------------------------------------
14 /* $Core: libIRCDtimer */
19 TimerManager::TimerManager(InspIRCd* Instance) : CantDeleteHere(false), ServerInstance(Instance)
23 void TimerManager::TickTimers(time_t TIME)
25 this->CantDeleteHere = true;
26 timerlist::iterator found = Timers.find(TIME);
28 if (found != Timers.end())
30 timergroup* x = found->second;
31 /* There are pending timers to trigger.
32 * WARNING: Timers may delete themselves from within
33 * their own Tick methods! see the comment below in
34 * the DelTimer method.
36 for (timergroup::iterator y = x->begin(); y != x->end(); y++)
42 AddTimer(n, n->GetSecs());
54 this->CantDeleteHere = false;
57 void TimerManager::DelTimer(Timer* T)
59 if (this->CantDeleteHere)
61 /* If a developer tries to delete a timer from within its own Tick method,
62 * then chances are this is just going to totally fuck over the timergroup
63 * and timerlist iterators and cause a crash. Thanks to peavey and Bricker
64 * for noticing this bug.
65 * If we're within the tick loop when the DelTimer is called (signified
66 * by the var 'CantDeleteHere') then we simply return for non-repeating
67 * timers, and cancel the repeat on repeating timers. We can do this because
68 * we know that the timer tick loop will safely delete the timer for us
69 * anyway and therefore we avoid stack corruption.
77 timerlist::iterator found = Timers.find(T->GetTimer());
79 if (found != Timers.end())
81 timergroup* x = found->second;
82 for (timergroup::iterator y = x->begin(); y != x->end(); y++)
100 /** Because some muppets may do odd things, and their ircd may lock up due
101 * to crappy 3rd party modules, or they may change their system time a bit,
102 * this accounts for shifts of up to 120 secs by looking behind for missed
103 * timers and executing them. This is only executed once every 5 secs.
104 * If you move your clock BACK, and your timers move further ahead as a result,
105 * then tough titty you'll just have to wait.
107 void TimerManager::TickMissedTimers(time_t TIME)
109 for (time_t n = TIME-1; n > TIME-120; n--)
110 this->TickTimers(TIME);
113 void TimerManager::AddTimer(Timer* T, long secs_from_now)
115 timergroup* x = NULL;
117 int time_to_trigger = 0;
119 time_to_trigger = T->GetTimer();
121 time_to_trigger = secs_from_now + ServerInstance->Time();
123 timerlist::iterator found = Timers.find(time_to_trigger);
125 if (found != Timers.end())
132 Timers[time_to_trigger] = x;