Scheduler: Implement PollTimerSource
[senf.git] / Scheduler / TimerSource.cc
1 // $Id$
2 //
3 // Copyright (C) 2009 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief TimerSource non-inline non-template implementation */
25
26 #include "TimerSource.hh"
27 //#include "TimerSource.ih"
28
29 // Custom includes
30 #include "FdEvent.hh"
31
32 //#include "TimerSource.mpp"
33 #define prefix_
34 ///////////////////////////////cc.p////////////////////////////////////////
35
36 ///////////////////////////////////////////////////////////////////////////
37 // senf::scheduler::detail::TimerSource
38
39 prefix_ senf::scheduler::detail::TimerSource::~TimerSource()
40 {}
41
42 ///////////////////////////////////////////////////////////////////////////
43 // senf::scheduler::detail::POSIXTimerSource
44
45 prefix_ senf::scheduler::detail::POSIXTimerSource::POSIXTimerSource()
46     : timeoutEnabled_ (false), timeout_ (0), signalEnabled_ (false)
47 {
48     if (pipe(timerPipe_) < 0)
49         SENF_THROW_SYSTEM_EXCEPTION("pipe()");
50     senf::scheduler::detail::FdManager::instance().set(
51         timerPipe_[0], detail::FdManager::EV_READ, this);
52     
53     sigemptyset(&sigSet_);
54     sigaddset(&sigSet_, SIGALRM);
55     sigprocmask(SIG_BLOCK, &sigSet_, 0);
56
57     struct sigaction act;
58     act.sa_sigaction = &sigHandler;
59     act.sa_mask = sigSet_;
60     act.sa_flags = SA_SIGINFO | SA_RESTART;
61     if (sigaction(SIGALRM, &act, 0) < 0)
62         SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
63
64     struct sigevent ev;
65     ::memset(&ev, 0, sizeof(ev));
66     ev.sigev_notify = SIGEV_SIGNAL;
67     ev.sigev_signo = SIGALRM;
68     ev.sigev_value.sival_ptr = this;
69     if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0)
70         SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
71 }
72
73 prefix_ senf::scheduler::detail::POSIXTimerSource::~POSIXTimerSource()
74 {
75     timer_delete(timerId_);
76     ::signal(SIGALRM, SIG_IGN);
77     sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
78     senf::scheduler::detail::FdManager::instance().remove(timerPipe_[0]);
79     close(timerPipe_[0]);
80     close(timerPipe_[1]);
81 }
82
83 prefix_ void
84 senf::scheduler::detail::POSIXTimerSource::timeout(ClockService::clock_type timeout)
85 {
86     if (! timeoutEnabled_ || timeout_ != timeout) {
87         timeout_ = timeout;
88         if (timeout_ <= 0)
89             timeout_ = 1;
90         timeoutEnabled_ = true;
91         reschedule();
92     }
93 }
94
95 prefix_ void senf::scheduler::detail::POSIXTimerSource::notimeout()
96 {
97     if (timeoutEnabled_) {
98         timeoutEnabled_ = false;
99         reschedule();
100     }
101 }
102
103 prefix_ void senf::scheduler::detail::POSIXTimerSource::enable()
104 {
105     if (! signalEnabled_) {
106         signalEnabled_ = true;
107         sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
108     }
109 }
110
111 prefix_ void senf::scheduler::detail::POSIXTimerSource::disable()
112 {
113     if (signalEnabled_) {
114         signalEnabled_ = false;
115         sigprocmask(SIG_BLOCK, &sigSet_, 0);
116     }
117 }
118
119 prefix_ void senf::scheduler::detail::POSIXTimerSource::sigHandler(int,
120                                                                    ::siginfo_t * siginfo,
121                                                                    void *)
122 {
123     if (siginfo->si_value.sival_ptr == 0)
124         return;
125     static char data = '\xD0';
126     write(static_cast<POSIXTimerSource*>(siginfo->si_value.sival_ptr)->timerPipe_[1], 
127           &data, sizeof(data));
128 }
129
130 prefix_ void senf::scheduler::detail::POSIXTimerSource::signal(int events)
131 {
132     char data;
133     read(timerPipe_[0], &data, sizeof(data));
134     timeoutEnabled_ = false;
135 }
136
137 prefix_ void senf::scheduler::detail::POSIXTimerSource::reschedule()
138 {
139     struct itimerspec timer;
140     memset(&timer, 0, sizeof(timer));
141     if (timeoutEnabled_) {
142         timer.it_value.tv_sec = ClockService::in_seconds(timeout_);
143         timer.it_value.tv_nsec = ClockService::in_nanoseconds(
144             timeout_ - ClockService::seconds(timer.it_value.tv_sec));
145     }
146     if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0)
147         SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
148 }
149
150 ///////////////////////////////////////////////////////////////////////////
151 // senf::scheduler::detail::PollTimerSource
152
153 prefix_ void senf::scheduler::detail::PollTimerSource::timeout(ClockService::clock_type timeout)
154 {
155     ClockService::clock_type now (ClockService::now());
156     int delay (ClockService::in_milliseconds(timeout-now)+1);
157     FileDispatcher::instance().timeout(delay<0?0:delay);
158 }
159
160 prefix_ void senf::scheduler::detail::PollTimerSource::notimeout()
161 {
162     FileDispatcher::instance().timeout(-1);
163 }
164
165 prefix_ void senf::scheduler::detail::PollTimerSource::enable()
166 {}
167
168 prefix_ void senf::scheduler::detail::PollTimerSource::disable()
169 {}
170
171 ///////////////////////////////cc.e////////////////////////////////////////
172 #undef prefix_
173 //#include "TimerSource.mpp"
174
175 \f
176 // Local Variables:
177 // mode: c++
178 // fill-column: 100
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"
184 // End: