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 "TimerEvent.hh"
27 #include "TimerEvent.ih"
31 //#include "TimerEvent.mpp"
33 ///////////////////////////////cc.p////////////////////////////////////////
35 prefix_ senf::scheduler::detail::TimerDispatcher::TimerDispatcher()
38 if (pipe(timerPipe_) < 0)
39 SENF_THROW_SYSTEM_EXCEPTION("pipe()");
40 senf::scheduler::FdManager::instance().set(timerPipe_[0], FdManager::EV_READ, this);
42 sigemptyset(&sigSet_);
43 sigaddset(&sigSet_, SIGALRM);
44 sigprocmask(SIG_BLOCK, &sigSet_, 0);
47 act.sa_sigaction = &sigHandler;
48 act.sa_mask = sigSet_;
49 act.sa_flags = SA_SIGINFO | SA_RESTART;
50 if (sigaction(SIGALRM, &act, 0) < 0)
51 SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
54 ::memset(&ev, 0, sizeof(ev));
55 ev.sigev_notify = SIGEV_SIGNAL;
56 ev.sigev_signo = SIGALRM;
57 ev.sigev_value.sival_ptr = this;
58 if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0)
59 SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
62 prefix_ senf::scheduler::detail::TimerDispatcher::~TimerDispatcher()
64 TimerSet::iterator i (timers_.begin());
65 TimerSet::iterator const i_end (timers_.end());
66 for (; i != i_end; ++i)
67 senf::scheduler::FIFORunner::instance().dequeue(&(*i));
69 timer_delete(timerId_);
70 ::signal(SIGALRM, SIG_IGN);
71 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
72 senf::scheduler::FdManager::instance().remove(timerPipe_[0]);
77 void senf::scheduler::detail::TimerDispatcher::add(TimerEvent & event)
79 TimerSet::iterator i (timers_.insert(event));
80 senf::scheduler::FIFORunner::instance().enqueue(&(*i));
85 prefix_ void senf::scheduler::detail::TimerDispatcher::remove(TimerEvent & event)
87 TimerSet::iterator i (TimerSet::current(event));
88 if (i == timers_.end())
90 senf::scheduler::FIFORunner::instance().dequeue(&(*i));
96 prefix_ void senf::scheduler::detail::TimerDispatcher::blockSignals()
100 sigprocmask(SIG_BLOCK, &sigSet_, 0);
104 prefix_ void senf::scheduler::detail::TimerDispatcher::unblockSignals()
109 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
113 prefix_ void senf::scheduler::detail::TimerDispatcher::signal(int events)
116 if (read(timerPipe_[0], &info, sizeof(info)) < int(sizeof(info)))
118 TimerSet::iterator i (timers_.begin());
119 TimerSet::iterator const i_end (timers_.end());
120 ClockService::clock_type now (senf::scheduler::FdManager::instance().eventTime());
121 for (; i != i_end && i->timeout_ <= now ; ++i)
125 prefix_ void senf::scheduler::detail::TimerDispatcher::sigHandler(int signal,
126 ::siginfo_t * siginfo,
129 // The manpage says, si_signo is unused in linux so we set it here
130 siginfo->si_signo = signal;
131 // We can't do much on error anyway so we ignore errors here
132 if (siginfo->si_value.sival_ptr == 0)
134 write(static_cast<TimerDispatcher*>(siginfo->si_value.sival_ptr)->timerPipe_[1],
135 siginfo, sizeof(*siginfo));
138 prefix_ void senf::scheduler::detail::TimerDispatcher::reschedule()
140 struct itimerspec timer;
141 memset(&timer, 0, sizeof(timer));
142 timer.it_interval.tv_sec = 0;
143 timer.it_interval.tv_nsec = 0;
144 if (timers_.empty()) {
145 SENF_LOG( (senf::log::VERBOSE)("Timer disabled") );
146 timer.it_value.tv_sec = 0;
147 timer.it_value.tv_nsec = 0;
150 ClockService::clock_type next (timers_.begin()->timeout_);
153 timer.it_value.tv_sec = ClockService::in_seconds(next);
154 timer.it_value.tv_nsec = ClockService::in_nanoseconds(
155 next - ClockService::seconds(timer.it_value.tv_sec));
156 SENF_LOG( (senf::log::VERBOSE)("Next timeout scheduled @" << timer.it_value.tv_sec << "."
157 << std::setw(9) << std::setfill('0') << timer.it_value.tv_nsec) );
159 if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0)
160 SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
163 ///////////////////////////////////////////////////////////////////////////
164 // senf::scheduler::detail::TimerDispatcher::TimerEvent
166 prefix_ void senf::scheduler::TimerEvent::run()
172 ///////////////////////////////cc.e////////////////////////////////////////
174 //#include "TimerEvent.mpp"
180 // comment-column: 40
181 // c-file-style: "senf"
182 // indent-tabs-mode: nil
183 // ispell-local-dictionary: "american"
184 // compile-command: "scons -u test"