4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
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 ClockService non-inline non-template implementation */
26 #include "ClockService.hh"
27 //#include "ClockService.ih"
34 #include "Utils/Exception.hh"
36 //#include "ClockService.mpp"
38 ///////////////////////////////cc.p////////////////////////////////////////
40 #define CheckErrno(op,args) if (op args < 0) throw SystemException(# op, errno)
42 struct senf::ClockService::Impl
50 Blocker(Impl * i) : impl(i) { impl->block(); }
51 ~Blocker() { impl->unblock(); }
55 static void timer(int);
57 struct sigaction oldaction;
58 struct itimerval olditimer;
62 prefix_ senf::ClockService::Impl::Impl()
64 CheckErrno( sigemptyset, (&alrm_set) );
65 CheckErrno( sigaddset, (&alrm_set, SIGALRM) );
68 prefix_ void senf::ClockService::Impl::block()
70 CheckErrno( sigprocmask, (SIG_BLOCK, &alrm_set, 0) );
73 prefix_ void senf::ClockService::Impl::unblock()
75 CheckErrno( sigprocmask, (SIG_UNBLOCK, &alrm_set, 0) );
78 prefix_ void senf::ClockService::Impl::timer(int)
80 boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time());
81 if (ClockService::instance().checkSkew(time))
82 ClockService::instance().clockSkew(
83 time, ClockService::instance().heartbeat_ + boost::posix_time::seconds(
84 ClockService::CheckInterval));
85 ClockService::instance().heartbeat_ = time;
88 ///////////////////////////////////////////////////////////////////////////
91 prefix_ senf::ClockService::~ClockService()
93 setitimer(ITIMER_REAL, &impl_->olditimer, 0);
94 sigaction(SIGALRM, &impl_->oldaction, 0);
97 ////////////////////////////////////////
100 prefix_ senf::ClockService::ClockService()
101 : base_ (boost::posix_time::microsec_clock::universal_time()),
102 heartbeat_ (base_), impl_(new ClockService::Impl())
104 struct sigaction action;
105 action.sa_handler = & senf::ClockService::Impl::timer;
106 CheckErrno( sigemptyset, (&action.sa_mask) );
107 action.sa_flags = SA_RESTART;
108 CheckErrno( sigaction, (SIGALRM, &action, &impl_->oldaction) );
110 struct itimerval itimer;
111 itimer.it_interval.tv_sec = CheckInterval;
112 itimer.it_interval.tv_usec = 0;
113 itimer.it_value.tv_sec = CheckInterval;
114 itimer.it_value.tv_usec = 0;
115 CheckErrno( setitimer, (ITIMER_REAL, &itimer, &impl_->olditimer) );
119 prefix_ void senf::ClockService::restart_i()
121 impl_->block(); // if any syscall fails, the alarm signal stays blocked which is correct
122 base_ = boost::posix_time::microsec_clock::universal_time();
125 struct sigaction action;
126 action.sa_handler = & senf::ClockService::Impl::timer;
127 CheckErrno( sigemptyset, (&action.sa_mask) );
128 action.sa_flags = SA_RESTART;
129 CheckErrno( sigaction, (SIGALRM, &action, 0) );
131 struct itimerval itimer;
132 itimer.it_interval.tv_sec = CheckInterval;
133 itimer.it_interval.tv_usec = 0;
134 itimer.it_value.tv_sec = CheckInterval;
135 itimer.it_value.tv_usec = 0;
136 CheckErrno( setitimer, (ITIMER_REAL, &itimer, 0) );
140 prefix_ void senf::ClockService::updateSkew(boost::posix_time::ptime time)
142 Impl::Blocker alrmBlocker (impl_.get());
143 struct itimerval itimer;
144 CheckErrno( getitimer, (ITIMER_REAL, &itimer) );
145 clockSkew(time, (heartbeat_
146 + boost::posix_time::seconds(CheckInterval)
147 - boost::posix_time::seconds(itimer.it_value.tv_sec)
148 - boost::posix_time::microseconds(itimer.it_value.tv_usec)));
151 ///////////////////////////////cc.e////////////////////////////////////////
153 //#include "ClockService.mpp"
159 // comment-column: 40
160 // c-file-style: "senf"
161 // indent-tabs-mode: nil
162 // ispell-local-dictionary: "american"
163 // compile-command: "scons -u test"