Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

Timer.h

00001 #ifndef _UNEVT_Timer_H_  // -*-c++-*-
00002 
00003 /*
00004  * Copyright 2002 Eric M. Hopper <hopper@omnifarious.org>
00005  * 
00006  *     This program is free software; you can redistribute it and/or modify it
00007  *     under the terms of the GNU Lesser General Public License as published
00008  *     by the Free Software Foundation; either version 2 of the License, or
00009  *     (at your option) any later version.
00010  * 
00011  *     This program is distributed in the hope that it will be useful, but
00012  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *     Lesser General Public License for more details.
00015  * 
00016  *     You should have received a copy of the GNU Lesser General Public
00017  *     License along with this program; if not, write to the Free Software
00018  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #ifdef __GNUG__
00022 #  pragma interface
00023 #endif
00024 
00025 /* $Header: /home/hopper/src/cvs/C++/UniEvent/UniEvent/Timer.h,v 1.8 2002/11/25 05:40:05 hopper Exp $ */
00026 
00027 // For a log, see ../ChangeLog
00028 // $Revision: 1.8 $
00029 // $Tag$
00030 
00031 #include <ctime>
00032 #include <iosfwd>
00033 #include <LCore/GenTypes.h>
00034 #include <LCore/Protocol.h>
00035 #include <UniEvent/UNEVT_ClassIdent.h>
00036 
00037 #define _UNEVT_Timer_H_
00038 
00039 namespace strmod {
00040 namespace unievent {
00041 
00042 class EventPtr;
00043 
00044 /** \class Timer Timer.h UniEvent/Timer.h
00045  * \brief Posts events that happen based on time.
00046  *
00047  * The ANSI C standard defines a rather anemic set of types for dealing with
00048  * time.  Worse, the exact values in most of the types are OS specific.  You
00049  * cannot count on time_t representing a value in the unit of seconds, for
00050  * example.
00051  *
00052  * Since this is supposed to a generic, OS agnostic interface, this leaves us in
00053  * something of a quandry.  The ANSI things _do_ tend to be focused on calendar
00054  * time though, so using our own interval type is perfectly reasonable.
00055  *
00056  * Given an interval type, it's reasonable to use the interval as an offset from
00057  * a time_t without encoding any knowledge of what a time_t actually represents
00058  * into the interface.
00059  *
00060  * It's tempting to use the rather well defined struct tm type until you examine
00061  * it closely and realize that it contains no provision for representing the
00062  * timezone.  Since it actually contains time information that would be
00063  * different in different timezones, this is a fatal lack.  A time_t is
00064  * sufficiently ambiguous that the questions of whether or not it is UTC or a
00065  * local time zone, and whether or not this can even be determined in the
00066  * environment are not important to the interface.
00067  */
00068 class Timer : virtual public lcore::Protocol
00069 {
00070  public:
00071    /** \class interval_t Timer.h UniEvent/Timer.h
00072     * \brief A span of time.
00073     * This interval is of only nanosecond precision.  If you need to time lasers
00074     * for photographing molecular interactions or schedule oscilloscope sweeps,
00075     * this class is probably not precise enough for you.  Then again, most OSes
00076     * are really iffy for anything less than millisecond resolution anyway.
00077     */
00078    struct interval_t {
00079       //@{
00080       /** These are public and not suffixed with '_' because they are part of
00081        * the public interface for this class.
00082        */
00083       unsigned long seconds;  //!< Seconds
00084       lcore::U4Byte nanoseconds;  //!< Billionths of a second.
00085       //@}
00086       inline interval_t(unsigned long secs = 0, lcore::U4Byte nanosecs = 0);
00087       inline void normalize();
00088    };
00089    //! The system time type.
00090    typedef ::time_t time_t;
00091    /** \class absolute_t Timer.h UniEvent/Timer.h
00092     * A particular nanosecond in all of eternity.
00093     */
00094    struct absolute_t : private interval_t {
00095       friend bool operator <(const absolute_t &a, const absolute_t &b);
00096       friend bool operator ==(const absolute_t &a, const absolute_t &b);
00097       friend const interval_t operator -(const absolute_t &a,
00098                                          const absolute_t &b);
00099       friend const absolute_t operator +(const absolute_t &a,
00100                                          const interval_t &b);
00101       time_t time;  //!< The OSes idea of an absolute time.
00102       interval_t::seconds;  //!< Seconds past \c time.
00103       interval_t::nanoseconds;  //!< Billionths of a second past \c time.
00104 
00105       inline absolute_t(time_t time_param,
00106                         unsigned long secs = 0, lcore::U4Byte nanosecs = 0) :
00107            interval_t(secs, nanosecs), time(time_param)
00108       {
00109       }
00110       inline absolute_t(time_t time_param, const interval_t &interval) :
00111            interval_t(interval), time(time_param)
00112       {
00113       }
00114       interval_t::normalize;
00115    };
00116    static const UNEVT_ClassIdent identifier;
00117 
00118    /** Construct a Timer
00119     */
00120    Timer()                                                       { }
00121    /** \brief Destroy a Timer.
00122     * All events and the times they were supposed to happen are forgotten.
00123     */
00124    virtual ~Timer()                                              { }
00125 
00126    virtual int AreYouA(const lcore::ClassIdent &cid) const {
00127       return (identifier == cid) || Protocol::AreYouA(cid);
00128    }
00129 
00130    //! Post an event at a particular time
00131    virtual void postAt(const absolute_t &t, const EventPtr &ev) = 0;
00132    //! Post an event after a certain amount of time has expired.
00133    virtual void postIn(const interval_t &off, const EventPtr &ev);
00134    //! What time is it now?!
00135    virtual absolute_t currentTime() const = 0;
00136 
00137  protected:
00138    virtual const lcore::ClassIdent *i_GetIdent() const  { return &identifier; }
00139 };
00140 
00141 //-----------------------------inline functions--------------------------------
00142 
00143 //! Construct a Timer::interval_t possibly from seconds and nanoseconds.
00144 inline Timer::interval_t::interval_t(unsigned long secs, lcore::U4Byte nanosecs)
00145      : seconds(secs), nanoseconds(nanosecs)
00146 {
00147    normalize();
00148 }
00149 
00150 //! Reduce nanoseconds to represent less than a full second.
00151 inline void Timer::interval_t::normalize()
00152 {
00153    if (nanoseconds >= 1000000000U)
00154    {
00155       seconds += (nanoseconds / 1000000000U);
00156       nanoseconds %= 1000000000U;
00157    }
00158 }
00159 
00160 bool operator <(const Timer::interval_t &a, const Timer::interval_t &b);
00161 
00162 inline bool operator >=(const Timer::interval_t &a, const Timer::interval_t &b)
00163 {
00164    return !(a < b);
00165 }
00166 
00167 inline bool operator >(const Timer::interval_t &a, const Timer::interval_t &b)
00168 {
00169    return b < a;
00170 }
00171 
00172 inline bool operator <=(const Timer::interval_t &a, const Timer::interval_t &b)
00173 {
00174    return !(b < a);
00175 }
00176 
00177 bool operator ==(const Timer::interval_t &a, const Timer::interval_t &b);
00178 
00179 inline bool operator !=(const Timer::interval_t &a, const Timer::interval_t &b)
00180 {
00181    return !(a == b);
00182 }
00183 
00184 //--
00185 
00186 bool operator <(const Timer::absolute_t &a, const Timer::absolute_t &b);
00187 
00188 inline bool operator >=(const Timer::absolute_t &a, const Timer::absolute_t &b)
00189 {
00190    return !(a < b);
00191 }
00192 
00193 inline bool operator >(const Timer::absolute_t &a, const Timer::absolute_t &b)
00194 {
00195    return b < a;
00196 }
00197 
00198 inline bool operator <=(const Timer::absolute_t &a, const Timer::absolute_t &b)
00199 {
00200    return !(b < a);
00201 }
00202 
00203 bool operator ==(const Timer::absolute_t &a, const Timer::absolute_t &b);
00204 
00205 inline bool operator !=(const Timer::absolute_t &a, const Timer::absolute_t &b)
00206 {
00207    return !(a == b);
00208 }
00209 
00210 //--
00211 
00212 //: Difference between two intervals, always >= 0
00213 const Timer::interval_t
00214 operator -(const Timer::interval_t &a, const Timer::interval_t &b);
00215 
00216 //: Sum of two intervals
00217 inline const Timer::interval_t
00218 operator +(const Timer::interval_t &a, const Timer::interval_t &b)
00219 {
00220    Timer::interval_t an = a;
00221    an.normalize();
00222    Timer::interval_t bn = b;
00223    bn.normalize();
00224    Timer::interval_t retval(an.seconds + bn.seconds,
00225                             an.nanoseconds + bn.nanoseconds);
00226    retval.normalize();
00227    return retval;
00228 }
00229 
00230 //: Interval between two absolute times, always >= 0
00231 const Timer::interval_t
00232 operator -(const Timer::absolute_t &a, const Timer::absolute_t &b);
00233 
00234 //: Add an interval to an absolute time.
00235 inline const Timer::absolute_t
00236 operator +(const Timer::absolute_t &a, const Timer::interval_t &b)
00237 {
00238    const Timer::interval_t &aint = a;
00239    Timer::absolute_t retval(a.time, aint + b);
00240    return retval;
00241 }
00242 
00243 ::std::ostream &operator <<(::std::ostream &os, const Timer::absolute_t &time);
00244 
00245 ::std::ostream &operator <<(::std::ostream &os, const Timer::interval_t &time);
00246 
00247 //--
00248 
00249 inline void
00250 Timer::postIn(const interval_t &off, const EventPtr &ev)
00251 {
00252    postAt(currentTime() + off, ev);
00253 }
00254 
00255 };  // namespace unievent
00256 };  // namespace strmod
00257 
00258 #endif

Generated on Wed Jan 29 00:32:45 2003 for libNet by doxygen1.3-rc1