X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Ftiming%2Ftimestamp.hxx;h=880d5dccd4baf080a85698e60e1afed74ac692bd;hb=7e7ce2f38e87d6244e05730fa4382da088bb25f1;hp=3a31ba58df9f89d7317999c3e6e32df500aa5450;hpb=e2b4c0787a4398199ef2d35e05963acd58b7a04c;p=simgear.git diff --git a/simgear/timing/timestamp.hxx b/simgear/timing/timestamp.hxx index 3a31ba58..880d5dcc 100644 --- a/simgear/timing/timestamp.hxx +++ b/simgear/timing/timestamp.hxx @@ -5,7 +5,7 @@ // Written by Curtis Olson, started December 1998. // -// Copyright (C) 1998 Curtis L. Olson - curt@flightgear.org +// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -19,7 +19,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -28,98 +28,248 @@ #define _TIMESTAMP_HXX -#ifndef __cplusplus +#ifndef __cplusplus # error This library requires C++ -#endif - +#endif +#include +#include +#include #include - - -// MSVC++ 6.0 kuldge - Need forward declaration of friends. -class SGTimeStamp; -SGTimeStamp operator + (const SGTimeStamp& t, const long& m); -long operator - (const SGTimeStamp& a, const SGTimeStamp& b); +#include /** * The SGTimeStamp class allows you to mark and compare time stamps - * with microsecond accuracy (if your system has support for this - * level of accuracy.) + * with nanosecond accuracy (if your system has support for this + * level of accuracy). * * The SGTimeStamp is useful for tracking the elapsed time of various * events in your program. You can also use it to keep constistant * motion across varying frame rates. + * + * Note SGTimestamp does not deliver the time of day. The content of this + * stamps might be, dependent on the implementation, a time to an arbitrary + * base time. */ class SGTimeStamp { +public: + typedef long sec_type; + typedef int nsec_type; -private: + /** Default constructor, initialize time to zero. */ + SGTimeStamp() : + _nsec(0), + _sec(0) + { } - long seconds; - long usec; + /** Hmm, might reenable them at some time, but since it is not clear + what the input unit of the int is, omit them for now. + Use the static constructor functions where it is clear from the method + name how the arguments are meant. + */ +// SGTimeStamp(sec_type sec) +// { setTime(sec, 0); } +// SGTimeStamp(int sec) +// { setTime(sec, 0); } +// SGTimeStamp(const double& sec) +// { setTime(sec); } -public: + /** Update stored time to current time (seconds and nanoseconds) */ + void stamp(); - /** Default constructor */ - SGTimeStamp(); + /** Set the time from a double value */ + void setTime(const double& seconds) + { + sec_type wholeSecs = sec_type(floor(seconds)); + nsec_type reminder; + reminder = nsec_type(floor((seconds - wholeSecs)*(1000*1000*1000))); + setTime(wholeSecs, reminder); + } + /** Set the time from a seconds/nanoseconds pair */ + void setTime(sec_type sec, nsec_type nsec) + { + if (0 <= nsec) { + _sec = sec + nsec / (1000*1000*1000); + _nsec = nsec % (1000*1000*1000); + } else { + _sec = sec - 1 + nsec / (1000*1000*1000); + _nsec = (1000*1000*1000) + nsec % (1000*1000*1000); + } + } - /** - * This creates an instance of the SGTimeStamp object. When - * calling the constructor you may provide initial seconds an - * microseconds values. - * @param s initial seconds value - * @param m initial microseconds value + + /** @return the saved seconds of this time stamp */ + long get_seconds() const { return _sec; } + + /** @return the saved microseconds of this time stamp */ + int get_usec() const { return _nsec/1000; } + + /** @return the saved seconds of this time stamp */ + const sec_type& getSeconds() const + { return _sec; } + /** @return the saved nanoseconds of this time stamp */ + const nsec_type& getNanoSeconds() const + { return _nsec; } + + /** @return the value of the timestamp in nanoseconds, + * use doubles to avoid overflow. + * If you need real nanosecond accuracy for time differences, build up a + * SGTimeStamp reference time and compare SGTimeStamps directly. */ - SGTimeStamp( const long s, const long m ); - ~SGTimeStamp(); + double toNSecs() const + { return _nsec + double(_sec)*1000*1000*1000; } - /** Update stored time to current time (seconds and microseconds) */ - void stamp(); + /** @return the value of the timestamp in microseconds, + * use doubles to avoid overflow. + * If you need real nanosecond accuracy for time differences, build up a + * SGTimeStamp reference time and compare SGTimeStamps directly. + */ + double toUSecs() const + { return 1e-3*_nsec + double(_sec)*1000*1000; } + + /** @return the value of the timestamp in milliseconds, + * use doubles to avoid overflow. + * If you need real nanosecond accuracy for time differences, build up a + * SGTimeStamp reference time and compare SGTimeStamps directly. + */ + double toMSecs() const + { return 1e-6*_nsec + double(_sec)*1000; } + + /** @return the value of the timestamp in seconds, + * use doubles to avoid overflow. + * If you need real nanosecond accuracy for time differences, build up a + * SGTimeStamp reference time and compare SGTimeStamps directly. + */ + double toSecs() const + { return 1e-9*_nsec + _sec; } + + /** Inplace addition. + */ + SGTimeStamp& operator+=(const SGTimeStamp& c) + { + _sec += c._sec; + _nsec += c._nsec; + if ((1000*1000*1000) <= _nsec) { + _nsec -= (1000*1000*1000); + _sec += 1; + } + return *this; + } - /** Compare two time stamps for equality */ - SGTimeStamp& operator = ( const SGTimeStamp& t ); + /** Inplace subtraction. + */ + SGTimeStamp& operator-=(const SGTimeStamp& c) + { + _sec -= c._sec; + _nsec -= c._nsec; + if (_nsec < 0) { + _nsec += (1000*1000*1000); + _sec -= 1; + } + return *this; + } /** - * Increment the saved time by the specified number of microseconds - * @param t time stamp - * @param m microseconds increment - * @return new time stamp + * Create SGTimeStamps from input with given units */ - friend SGTimeStamp operator + (const SGTimeStamp& t, const long& m); + static SGTimeStamp fromSecMSec(sec_type sec, nsec_type msec) + { return SGTimeStamp(sec, 1000*1000*msec); } + static SGTimeStamp fromSecUSec(sec_type sec, nsec_type usec) + { return SGTimeStamp(sec, 1000*usec); } + static SGTimeStamp fromSecNSec(sec_type sec, nsec_type nsec) + { return SGTimeStamp(sec, nsec); } + + static SGTimeStamp fromSec(int sec) + { SGTimeStamp ts; ts.setTime(sec); return ts; } + static SGTimeStamp fromSec(const double& sec) + { SGTimeStamp ts; ts.setTime(sec); return ts; } + static SGTimeStamp fromUSec(nsec_type usec) + { return SGTimeStamp(0, 1000*usec); } + static SGTimeStamp fromNSec(nsec_type nsec) + { return SGTimeStamp(0, nsec); } /** - * Subtract two time stamps returning the difference in microseconds. - * @param a timestamp 1 - * @param b timestame 2 - * @return difference in microseconds + * Return a timestamp with the current time. */ - friend long operator - (const SGTimeStamp& a, const SGTimeStamp& b); + static SGTimeStamp now() + { SGTimeStamp ts; ts.stamp(); return ts; } - /** @return the saved seconds of this time stamp */ - inline long get_seconds() const { return seconds; } +private: + SGTimeStamp(sec_type sec, nsec_type nsec) + { setTime(sec, nsec); } - /** @return the saved microseconds of this time stamp */ - inline long get_usec() const { return usec; } + nsec_type _nsec; + sec_type _sec; }; -inline SGTimeStamp::SGTimeStamp() { +inline bool +operator==(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ + if (c1.getNanoSeconds() != c2.getNanoSeconds()) + return false; + return c1.getSeconds() == c2.getSeconds(); } -inline SGTimeStamp::SGTimeStamp( const long s, const long u ) { - seconds = s; - usec = u; -} +inline bool +operator!=(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ return !operator==(c1, c2); } -inline SGTimeStamp::~SGTimeStamp() { +inline bool +operator<(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ + if (c1.getSeconds() < c2.getSeconds()) + return true; + if (c1.getSeconds() > c2.getSeconds()) + return false; + return c1.getNanoSeconds() < c2.getNanoSeconds(); } -inline SGTimeStamp& SGTimeStamp::operator = (const SGTimeStamp& t) +inline bool +operator>(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ return c2 < c1; } + +inline bool +operator>=(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ return !(c1 < c2); } + +inline bool +operator<=(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ return !(c1 > c2); } + +inline SGTimeStamp +operator+(const SGTimeStamp& c1) +{ return c1; } + +inline SGTimeStamp +operator-(const SGTimeStamp& c1) +{ return SGTimeStamp::fromSec(0) -= c1; } + +inline SGTimeStamp +operator+(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ return SGTimeStamp(c1) += c2; } + +inline SGTimeStamp +operator-(const SGTimeStamp& c1, const SGTimeStamp& c2) +{ return SGTimeStamp(c1) -= c2; } + +template +inline +std::basic_ostream& +operator<<(std::basic_ostream& os, const SGTimeStamp& c) { - seconds = t.seconds; - usec = t.usec; - return *this; -} + std::basic_stringstream stream; + SGTimeStamp pos = c; + if (c.getSeconds() < 0) { + stream << stream.widen('-'); + pos = - c; + } + stream << pos.getSeconds() << stream.widen('.'); + stream << std::setw(9) << std::setfill('0') << pos.getNanoSeconds(); + + return os << stream.str(); +} #endif // _TIMESTAMP_HXX