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"
32 //#include "TimerEvent.mpp"
34 ///////////////////////////////cc.p////////////////////////////////////////
36 prefix_ senf::scheduler::detail::TimerDispatcher::TimerDispatcher()
39 if (pipe(timerPipe_) < 0)
40 SENF_THROW_SYSTEM_EXCEPTION("pipe()");
41 senf::scheduler::detail::FdManager::instance().set(timerPipe_[0], detail::FdManager::EV_READ, this);
43 sigemptyset(&sigSet_);
44 sigaddset(&sigSet_, SIGALRM);
45 sigprocmask(SIG_BLOCK, &sigSet_, 0);
48 act.sa_sigaction = &sigHandler;
49 act.sa_mask = sigSet_;
50 act.sa_flags = SA_SIGINFO | SA_RESTART;
51 if (sigaction(SIGALRM, &act, 0) < 0)
52 SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
55 ::memset(&ev, 0, sizeof(ev));
56 ev.sigev_notify = SIGEV_SIGNAL;
57 ev.sigev_signo = SIGALRM;
58 ev.sigev_value.sival_ptr = this;
59 if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0)
60 SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
63 prefix_ senf::scheduler::detail::TimerDispatcher::~TimerDispatcher()
65 TimerSet::iterator i (timers_.begin());
66 TimerSet::iterator const i_end (timers_.end());
67 for (; i != i_end; ++i)
68 senf::scheduler::detail::FIFORunner::instance().dequeue(&(*i));
70 timer_delete(timerId_);
71 ::signal(SIGALRM, SIG_IGN);
72 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
73 senf::scheduler::detail::FdManager::instance().remove(timerPipe_[0]);
78 void senf::scheduler::detail::TimerDispatcher::add(TimerEvent & event)
80 TimerSet::iterator i (timers_.insert(event));
81 senf::scheduler::detail::FIFORunner::instance().enqueue(&(*i));
86 prefix_ void senf::scheduler::detail::TimerDispatcher::remove(TimerEvent & event)
88 TimerSet::iterator i (TimerSet::current(event));
89 if (i == timers_.end())
91 senf::scheduler::detail::FIFORunner::instance().dequeue(&(*i));
97 prefix_ void senf::scheduler::detail::TimerDispatcher::blockSignals()
101 sigprocmask(SIG_BLOCK, &sigSet_, 0);
105 prefix_ void senf::scheduler::detail::TimerDispatcher::unblockSignals()
110 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
114 prefix_ void senf::scheduler::detail::TimerDispatcher::signal(int events)
117 if (read(timerPipe_[0], &info, sizeof(info)) < int(sizeof(info)))
119 TimerSet::iterator i (timers_.begin());
120 TimerSet::iterator const i_end (timers_.end());
121 ClockService::clock_type now (senf::scheduler::detail::FdManager::instance().eventTime());
122 for (; i != i_end && i->timeout_ <= now ; ++i)
126 prefix_ void senf::scheduler::detail::TimerDispatcher::sigHandler(int signal,
127 ::siginfo_t * siginfo,
130 // The manpage says, si_signo is unused in linux so we set it here
131 siginfo->si_signo = signal;
132 // We can't do much on error anyway so we ignore errors here
133 if (siginfo->si_value.sival_ptr == 0)
135 write(static_cast<TimerDispatcher*>(siginfo->si_value.sival_ptr)->timerPipe_[1],
136 siginfo, sizeof(*siginfo));
139 prefix_ void senf::scheduler::detail::TimerDispatcher::reschedule()
141 struct itimerspec timer;
142 memset(&timer, 0, sizeof(timer));
143 timer.it_interval.tv_sec = 0;
144 timer.it_interval.tv_nsec = 0;
145 if (timers_.empty()) {
146 SENF_LOG( (senf::log::VERBOSE)("Timer disabled") );
147 timer.it_value.tv_sec = 0;
148 timer.it_value.tv_nsec = 0;
151 ClockService::clock_type next (timers_.begin()->timeout_);
154 timer.it_value.tv_sec = ClockService::in_seconds(next);
155 timer.it_value.tv_nsec = ClockService::in_nanoseconds(
156 next - ClockService::seconds(timer.it_value.tv_sec));
157 SENF_LOG( (senf::log::VERBOSE)("Next timeout scheduled @" << timer.it_value.tv_sec << "."
158 << std::setw(9) << std::setfill('0') << timer.it_value.tv_nsec) );
160 if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0)
161 SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
164 ///////////////////////////////////////////////////////////////////////////
165 // senf::scheduler::detail::TimerDispatcher::TimerEvent
167 prefix_ void senf::scheduler::TimerEvent::v_run()
173 prefix_ char const * senf::scheduler::TimerEvent::v_type()
179 prefix_ std::string senf::scheduler::TimerEvent::v_info()
182 std::stringstream ss;
183 ss.imbue( std::locale(ss.getloc(),
184 new boost::posix_time::time_facet("%Y-%m-%d %H:%M:%S.%f-0000")) );
185 ss << "expire " << ClockService::abstime(timeout_);
189 ///////////////////////////////cc.e////////////////////////////////////////
191 //#include "TimerEvent.mpp"
197 // comment-column: 40
198 // c-file-style: "senf"
199 // indent-tabs-mode: nil
200 // ispell-local-dictionary: "american"
201 // compile-command: "scons -u test"