Fawkes API  Fawkes Development Version
clock.cpp
00001 
00002 /***************************************************************************
00003  *  clock.cpp - A central clock
00004  *
00005  *  Created: Sun Jun 03 00:23:59 2007
00006  *  Copyright  2007       Daniel Beck 
00007  *             2007-2008  Tim Niemueller [www.niemueller.de]
00008  *
00009  ****************************************************************************/
00010 
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024 
00025 #include <utils/time/clock.h>
00026 #include <utils/time/timesource.h>
00027 #include <utils/logging/liblogger.h>
00028 
00029 #include <cstdlib>
00030 
00031 namespace fawkes {
00032 
00033 /** @class Clock clock.h <utils/time/clock.h>
00034  * This is supposed to be the central clock in Fawkes.
00035  * It is implemented as a singleton to ensure that there is only
00036  * one object. So-called TimeSources can be registered at the Clock
00037  * their current time can be retrieved through the Clock.
00038  * @author Daniel Beck, Tim Niemueller
00039  */
00040 
00041 /** initialize static members */
00042 Clock* Clock::_instance = NULL;
00043 bool Clock::destruct_ok = false;
00044 
00045 /** Constructor. */
00046 Clock::Clock()
00047 {
00048   destruct_ok = false;
00049   ext_timesource = 0;
00050   ext_default = false;
00051 }
00052 
00053 
00054 /** Destructor.
00055  * Generates a log message if Clock::finalize wasn't called beforehand 
00056  */
00057 Clock::~Clock()
00058 {
00059   if ( !destruct_ok ) {
00060     LibLogger::log_error("Clock", "dtor called without calling Clock::finalize() first");
00061   }
00062 
00063   delete ext_timesource;
00064 }
00065 
00066 
00067 /** Clock initializer.
00068  * This one is static and has to be called to instantiate a Clock object.
00069  * In further calls it just returns a pointer to the Clock object.
00070  * @return a pointer to the Clock object
00071  */
00072 Clock *
00073 Clock::instance()
00074 {
00075   if ( NULL == _instance )
00076     {
00077       _instance = new Clock();
00078     }
00079   
00080   return _instance;
00081 }
00082 
00083 
00084 /** Finalize.
00085  * Sets a boolean flag which prevents a log message from being generated in
00086  * the destructor.
00087  */
00088 void
00089 Clock::finalize()
00090 {
00091   destruct_ok = true;
00092   delete _instance;
00093   _instance = NULL;
00094 }
00095 
00096 
00097 /** Register an external time source.
00098  * 
00099  * @param ts a pointer to the external time source
00100  * @param make_default if true, this time source is made the default
00101  * timesource which means that for every call of get_time() the time
00102  * of the external time source is returned
00103  */
00104 void
00105 Clock::register_ext_timesource(TimeSource* ts, bool make_default)
00106 {
00107   ext_timesource = ts;
00108 
00109   if (make_default) {
00110     ext_default = true;
00111   }
00112 }
00113 
00114 
00115 /** Remove external time source.
00116  * If an external timesource is currently set it is removed. The time source
00117  * will not be deleted but only the reference to it is removed.
00118  * @param ts only remove time source if it equals ts, if NULL remove no matter what.
00119  */
00120 void
00121 Clock::remove_ext_timesource(TimeSource *ts)
00122 {
00123   if ( (ts == NULL) || (ext_timesource == ts) ) {
00124     ext_timesource = NULL;
00125     ext_default = false;
00126   } else {
00127     throw Exception("Time sources do not match. Not removing.");
00128   }
00129 }
00130 
00131 
00132 /** Set/unset the external time source as the default time source.
00133  * @param ext_is_default true to make external time source the default,
00134  * false to disable it as the default.
00135  */
00136 void
00137 Clock::set_ext_default_timesource(bool ext_is_default)
00138 {
00139   if ( ext_is_default ) {
00140     if (NULL != ext_timesource) {
00141       ext_default = true;
00142     } else {
00143       throw Exception("Trying to make the external timesource the default timesource but there is no external timesource");
00144     }
00145   } else {
00146     ext_default = false;
00147   }
00148 }
00149 
00150 
00151 /** Checks whether the external time source is the default time soucre.
00152  * @return true if external time source is default time source
00153  */
00154 bool
00155 Clock::is_ext_default_timesource() const
00156 {
00157   return ext_default;
00158 }
00159 
00160 
00161 /** Returns the time of the selected time source.
00162  * @param tv pointer to a timeval struct where the time is written to
00163  * @param sel allows to select the time source
00164  */
00165 void
00166 Clock::get_time(struct timeval* tv, TimesourceSelector sel) const
00167 {
00168   if ( (DEFAULT == sel && !ext_default) ||
00169        REALTIME == sel)
00170     {
00171       gettimeofday(tv, 0);
00172     }
00173   else if ( (EXTERNAL == sel) && 
00174             (NULL == ext_timesource) )
00175     {
00176       throw Exception("No external time source registered");
00177     }
00178   else
00179     {
00180       ext_timesource->get_time(tv);
00181     }
00182 }
00183 
00184 
00185 /** Returns the time of the selected time source.
00186  * @param tv pointer to a timeval struct where the time is written to
00187  */
00188 void
00189 Clock::get_time(struct timeval* tv) const
00190 {
00191   if ( ext_default ) {
00192     if ( NULL == ext_timesource ) {
00193       throw Exception("No external time source registered");
00194     }
00195     ext_timesource->get_time(tv);
00196   } else {
00197     gettimeofday(tv, NULL);
00198   }
00199 }
00200 
00201 
00202 /** Returns the time of the selected time source.
00203  * @param time reference to a time where the result is stored
00204  */
00205 void
00206 Clock::get_time(Time &time) const
00207 {
00208   get_time(&(time.__time));
00209 }
00210 
00211 
00212 
00213 
00214 /** Returns the time of the selected time source.
00215  * @param time reference to a time where the result is stored
00216  * @param sel allows to select the time source
00217  */
00218 void
00219 Clock::get_time(Time &time, TimesourceSelector sel) const
00220 {
00221   get_time(&(time.__time), sel);
00222 }
00223 
00224 
00225 /** Returns the time of the selected time source.
00226  * @param time pointer to a Time instance
00227  */
00228 void
00229 Clock::get_time(Time *time) const
00230 {
00231   get_time(&(time->__time));
00232 }
00233 
00234 
00235 
00236 
00237 /** Returns the time of the selected time source.
00238  * @param time pointer to a Time instance where the time is stored
00239  * @param sel allows to select the time source
00240  */
00241 void
00242 Clock::get_time(Time *time, TimesourceSelector sel) const
00243 {
00244   get_time(&(time->__time), sel);
00245 }
00246 
00247 
00248 /** Returns the system time.
00249  * @param tv pointer to a timeval struct where the time is written to
00250  */
00251 void
00252 Clock::get_systime(struct timeval* tv) const
00253 {
00254   gettimeofday(tv, 0);
00255 }
00256 
00257 
00258 /** Returns the time of the selected time source.
00259  * @param time reference to Time instance where the time is stored
00260  */
00261 void
00262 Clock::get_systime(Time &time) const
00263 {
00264   gettimeofday(&(time.__time), 0);
00265 }
00266 
00267 
00268 /** Returns the time of the selected time source.
00269  * @param time pointer to Time instance where the time is stored
00270  */
00271 void
00272 Clock::get_systime(Time *time) const
00273 {
00274   gettimeofday(&(time->__time), 0);
00275 }
00276 
00277 
00278 /** Get the current time.
00279  * @return current time
00280  */
00281 Time
00282 Clock::now() const
00283 {
00284   Time t(_instance);
00285   return t.stamp();
00286 }
00287 
00288 
00289 /** How much time has elapsed since t?
00290  * Calculated as "now - t" in seconds.
00291  * @param t time
00292  * @return elapsed seconds
00293  */
00294 float
00295 Clock::elapsed(Time *t) const
00296 {
00297   Time nowt(_instance);
00298   return nowt - t;
00299 }
00300 
00301 
00302 /** How much system time has elapsed since t?
00303  * Use only for system time criteria like timeouts.
00304  * @param t time
00305  * @return elapsed system seconds
00306  */
00307 float
00308 Clock::sys_elapsed(Time *t) const
00309 {
00310   struct timeval nowt;
00311   gettimeofday(&nowt, NULL);
00312   return time_diff_sec(nowt, t->__time);
00313 }
00314 
00315 
00316 /** Convert a time given w.r.t. the external time source into the system time.
00317  * @param t the time that is converted to the system time
00318  * @return the time in system time
00319  */ 
00320 Time
00321 Clock::ext_to_realtime(const Time& t)
00322 {
00323   timeval tv;
00324   Time ret;
00325   
00326   if (NULL != ext_timesource) 
00327     {
00328       tv = ext_timesource->conv_to_realtime(t.get_timeval());
00329       ret.set_time(&tv); 
00330     }
00331   else 
00332     {
00333       ret = t;
00334     }
00335 
00336   return ret;
00337 }
00338 
00339 
00340 /** Check whether an external time source is registered.
00341  * @return true if an external time source is registered
00342  */
00343 bool
00344 Clock::has_ext_timesource() const
00345 {
00346   if (0 != ext_timesource) {
00347     return true;
00348   } else {
00349     return false;
00350   }
00351 }
00352 
00353 } // end namespace fawkes