4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief TimerDispatcher non-inline non-template implementation */
26 #include "TimerDispatcher.hh"
27 //#include "TimerDispatcher.ih"
31 //#include "TimerDispatcher.mpp"
33 ///////////////////////////////cc.p////////////////////////////////////////
35 unsigned senf::scheduler::TimerDispatcher::useCount_ (0);
37 prefix_ senf::scheduler::TimerDispatcher::TimerDispatcher(FdManager & manager,
39 : manager_ (manager), runner_ (runner), lastId_ (0), blocked_ (true)
41 if (pipe(timerPipe_) < 0)
42 SENF_THROW_SYSTEM_EXCEPTION("pipe()");
43 manager_.set(timerPipe_[0], FdManager::EV_READ, this);
45 sigemptyset(&sigSet_);
46 sigaddset(&sigSet_, SIGALRM);
47 sigprocmask(SIG_BLOCK, &sigSet_, 0);
51 act.sa_sigaction = &sigHandler;
52 act.sa_mask = sigSet_;
53 act.sa_flags = SA_SIGINFO | SA_RESTART;
54 if (sigaction(SIGALRM, &act, 0) < 0)
55 SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
59 ev.sigev_notify = SIGEV_SIGNAL;
60 ev.sigev_signo = SIGALRM;
61 ev.sigev_value.sival_ptr = this;
62 if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0)
63 SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
68 prefix_ senf::scheduler::TimerDispatcher::~TimerDispatcher()
72 TimerMap::iterator i (timers_.begin());
73 TimerMap::iterator const i_end (timers_.end());
74 for (; i != i_end; ++i)
75 runner_.dequeue(&(i->second));
77 timer_delete(timerId_);
79 ::signal(SIGALRM, SIG_IGN);
80 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
81 manager_.remove(timerPipe_[0]);
86 prefix_ senf::scheduler::TimerDispatcher::timer_id
87 senf::scheduler::TimerDispatcher::add(ClockService::clock_type timeout, Callback const & cb)
89 while (timerIdIndex_.find(++lastId_) != timerIdIndex_.end()) ;
90 TimerMap::iterator i (timers_.insert(std::make_pair(timeout, TimerEvent(lastId_, cb, *this))));
91 timerIdIndex_.insert(std::make_pair(lastId_, i));
92 runner_.enqueue(&(i->second));
98 prefix_ void senf::scheduler::TimerDispatcher::remove(timer_id id)
100 TimerIdMap::iterator i (timerIdIndex_.find(id));
101 if (i == timerIdIndex_.end())
103 runner_.dequeue(&(i->second->second));
104 timers_.erase(i->second);
105 timerIdIndex_.erase(i);
110 prefix_ void senf::scheduler::TimerDispatcher::blockSignals()
114 sigprocmask(SIG_BLOCK, &sigSet_, 0);
118 prefix_ void senf::scheduler::TimerDispatcher::unblockSignals()
123 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
127 prefix_ void senf::scheduler::TimerDispatcher::signal(int events)
130 if (read(timerPipe_[0], &info, sizeof(info)) < int(sizeof(info)))
133 TimerMap::iterator i (timers_.begin());
134 TimerMap::iterator const i_end (timers_.end());
135 ClockService::clock_type now (ClockService::now());
136 for (; i != i_end && i->first <= now ; ++i)
137 i->second.runnable = true;
140 prefix_ void senf::scheduler::TimerDispatcher::sigHandler(int signal, ::siginfo_t * siginfo,
143 // The manpage says, si_signo is unused in linux so we set it here
144 siginfo->si_signo = signal;
145 // We can't do much on error anyway so we ignore errors here
146 if (siginfo->si_value.sival_ptr == 0)
148 write(static_cast<TimerDispatcher*>(siginfo->si_value.sival_ptr)->timerPipe_[1],
149 siginfo, sizeof(*siginfo));
152 prefix_ void senf::scheduler::TimerDispatcher::reschedule()
154 struct itimerspec timer;
155 timer.it_interval.tv_sec = 0;
156 timer.it_interval.tv_nsec = 0;
157 if (timers_.empty()) {
158 timer.it_value.tv_sec = 0;
159 timer.it_value.tv_nsec = 0;
162 ClockService::clock_type next (timers_.begin()->first);
163 timer.it_value.tv_sec = ClockService::in_seconds(next);
164 timer.it_value.tv_nsec = ClockService::in_nanoseconds(
165 next - ClockService::seconds(timer.it_value.tv_sec));
167 if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0)
168 SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
171 ///////////////////////////////cc.e////////////////////////////////////////
173 //#include "TimerDispatcher.mpp"
179 // comment-column: 40
180 // c-file-style: "senf"
181 // indent-tabs-mode: nil
182 // ispell-local-dictionary: "american"
183 // compile-command: "scons -u test"