17d2de7eb91aef46cf967fec2a1ef308d5686182
[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
31 //#include "TimerSource.mpp"
32 #define prefix_
33 ///////////////////////////////cc.p////////////////////////////////////////
34
35 ///////////////////////////////////////////////////////////////////////////
36 // senf::scheduler::detail::TimerSource
37
38 prefix_ senf::scheduler::detail::TimerSource::~TimerSource()
39 {}
40
41 ///////////////////////////////////////////////////////////////////////////
42 // senf::scheduler::detail::POSIXTimerSource
43
44 prefix_ senf::scheduler::detail::POSIXTimerSource::POSIXTimerSource()
45     : timeoutEnabled_ (false), timeout_ (0), signalEnabled_ (false)
46 {
47     if (pipe(timerPipe_) < 0)
48         SENF_THROW_SYSTEM_EXCEPTION("pipe()");
49     senf::scheduler::detail::FdManager::instance().set(
50         timerPipe_[0], detail::FdManager::EV_READ, this);
51     
52     sigemptyset(&sigSet_);
53     sigaddset(&sigSet_, SIGALRM);
54     sigprocmask(SIG_BLOCK, &sigSet_, 0);
55
56     struct sigaction act;
57     act.sa_sigaction = &sigHandler;
58     act.sa_mask = sigSet_;
59     act.sa_flags = SA_SIGINFO | SA_RESTART;
60     if (sigaction(SIGALRM, &act, 0) < 0)
61         SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
62
63     struct sigevent ev;
64     ::memset(&ev, 0, sizeof(ev));
65     ev.sigev_notify = SIGEV_SIGNAL;
66     ev.sigev_signo = SIGALRM;
67     ev.sigev_value.sival_ptr = this;
68     if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0)
69         SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
70 }
71
72 prefix_ senf::scheduler::detail::POSIXTimerSource::~POSIXTimerSource()
73 {
74     timer_delete(timerId_);
75     ::signal(SIGALRM, SIG_IGN);
76     sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
77     senf::scheduler::detail::FdManager::instance().remove(timerPipe_[0]);
78     close(timerPipe_[0]);
79     close(timerPipe_[1]);
80 }
81
82 prefix_ void
83 senf::scheduler::detail::POSIXTimerSource::timeout(ClockService::clock_type timeout)
84 {
85     if (! timeoutEnabled_ || timeout_ != timeout) {
86         timeout_ = timeout;
87         if (timeout_ <= 0)
88             timeout_ = 1;
89         timeoutEnabled_ = true;
90         reschedule();
91     }
92 }
93
94 prefix_ void senf::scheduler::detail::POSIXTimerSource::notimeout()
95 {
96     if (timeoutEnabled_) {
97         timeoutEnabled_ = false;
98         reschedule();
99     }
100 }
101
102 prefix_ void senf::scheduler::detail::POSIXTimerSource::enable()
103 {
104     if (! signalEnabled_) {
105         signalEnabled_ = true;
106         sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
107     }
108 }
109
110 prefix_ void senf::scheduler::detail::POSIXTimerSource::disable()
111 {
112     if (signalEnabled_) {
113         signalEnabled_ = false;
114         sigprocmask(SIG_BLOCK, &sigSet_, 0);
115     }
116 }
117
118 prefix_ void senf::scheduler::detail::POSIXTimerSource::sigHandler(int,
119                                                                    ::siginfo_t * siginfo,
120                                                                    void *)
121 {
122     if (siginfo->si_value.sival_ptr == 0)
123         return;
124     static char data = '\xD0';
125     write(static_cast<POSIXTimerSource*>(siginfo->si_value.sival_ptr)->timerPipe_[1], 
126           &data, sizeof(data));
127 }
128
129 prefix_ void senf::scheduler::detail::POSIXTimerSource::signal(int events)
130 {
131     char data;
132     read(timerPipe_[0], &data, sizeof(data));
133     timeoutEnabled_ = false;
134 }
135
136 prefix_ void senf::scheduler::detail::POSIXTimerSource::reschedule()
137 {
138     struct itimerspec timer;
139     memset(&timer, 0, sizeof(timer));
140     if (timeoutEnabled_) {
141         timer.it_value.tv_sec = ClockService::in_seconds(timeout_);
142         timer.it_value.tv_nsec = ClockService::in_nanoseconds(
143             timeout_ - ClockService::seconds(timer.it_value.tv_sec));
144     }
145     if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0)
146         SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
147 }
148
149 ///////////////////////////////cc.e////////////////////////////////////////
150 #undef prefix_
151 //#include "TimerSource.mpp"
152
153 \f
154 // Local Variables:
155 // mode: c++
156 // fill-column: 100
157 // comment-column: 40
158 // c-file-style: "senf"
159 // indent-tabs-mode: nil
160 // ispell-local-dictionary: "american"
161 // compile-command: "scons -u test"
162 // End: