// // ZoneMinder Time Functions & Definitions, $Date$, $Revision$ // Copyright (C) 2001-2008 Philip Coombes // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // #ifndef ZM_TIME_H #define ZM_TIME_H #include "zm_logger.h" #include #include // Structure used for storing the results of the subtraction // of one struct timeval from another struct DeltaTimeval { bool positive; unsigned long delta; unsigned long sec; unsigned long fsec; unsigned long prec; }; #define DT_GRAN_1000000 1000000 #define DT_PREC_6 DT_GRAN_1000000 #define DT_GRAN_100000 100000 #define DT_PREC_5 DT_GRAN_100000 #define DT_GRAN_10000 10000 #define DT_PREC_4 DT_GRAN_10000 #define DT_GRAN_1000 1000 #define DT_PREC_3 DT_GRAN_1000 #define DT_GRAN_100 100 #define DT_PREC_2 DT_GRAN_100 #define DT_GRAN_10 10 #define DT_PREC_1 DT_GRAN_10 #define DT_MAXGRAN DT_GRAN_1000000 #define USEC_PER_SEC 1000000 #define MSEC_PER_SEC 1000 /* extern struct timeval tv; */ inline int tvDiffUsec( struct timeval first, struct timeval last ) { return( (last.tv_sec - first.tv_sec) * USEC_PER_SEC) + ((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC ); } inline int tvDiffUsec( struct timeval first ) { struct timeval now; gettimeofday( &now, nullptr ); return( tvDiffUsec( first, now ) ); } inline int tvDiffMsec( struct timeval first, struct timeval last ) { return( (last.tv_sec - first.tv_sec) * MSEC_PER_SEC) + (((MSEC_PER_SEC + last.tv_usec - first.tv_usec) / MSEC_PER_SEC) - MSEC_PER_SEC ); } inline int tvDiffMsec( struct timeval first ) { struct timeval now; gettimeofday( &now, nullptr ); return( tvDiffMsec( first, now ) ); } inline double tvDiffSec( struct timeval first, struct timeval last ) { return( double(last.tv_sec - first.tv_sec) + double(((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC) / (1.0*USEC_PER_SEC) ) ); } inline double tvDiffSec( struct timeval first ) { struct timeval now; gettimeofday( &now, nullptr ); return( tvDiffSec( first, now ) ); } inline struct timeval tvZero() { struct timeval t = { 0, 0 }; return( t ); } inline int tvIsZero( const struct timeval t ) { return( t.tv_sec == 0 && t.tv_usec == 0 ); } inline int tvCmp( struct timeval t1, struct timeval t2 ) { if ( t1.tv_sec < t2.tv_sec ) return( -1 ); if ( t1.tv_sec > t2.tv_sec ) return( 1 ); if ( t1.tv_usec < t2.tv_usec ) return( -1 ); if ( t1.tv_usec > t2.tv_usec ) return( 1 ); return( 0 ); } inline int tvEq( struct timeval t1, struct timeval t2 ) { return( t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec ); } inline struct timeval tvNow( void ) { struct timeval t; gettimeofday( &t, nullptr ); return( t ); } inline struct timeval tvCheck( struct timeval &t ) { if ( t.tv_usec >= USEC_PER_SEC ) { Warning( "Timestamp too large %ld.%ld\n", t.tv_sec, (long int) t.tv_usec ); t.tv_sec += t.tv_usec / USEC_PER_SEC; t.tv_usec %= USEC_PER_SEC; } else if ( t.tv_usec < 0 ) { Warning( "Got negative timestamp %ld.%ld\n", t.tv_sec, (long int)t.tv_usec ); t.tv_usec = 0; } return( t ); } // Add t2 to t1 inline struct timeval tvAdd( struct timeval t1, struct timeval t2 ) { tvCheck(t1); tvCheck(t2); t1.tv_sec += t2.tv_sec; t1.tv_usec += t2.tv_usec; if ( t1.tv_usec >= USEC_PER_SEC ) { t1.tv_sec++; t1.tv_usec -= USEC_PER_SEC; } return( t1 ); } // Subtract t2 from t1 inline struct timeval tvSub( struct timeval t1, struct timeval t2 ) { tvCheck(t1); tvCheck(t2); t1.tv_sec -= t2.tv_sec; t1.tv_usec -= t2.tv_usec; if ( t1.tv_usec < 0 ) { t1.tv_sec--; t1.tv_usec += USEC_PER_SEC; } return( t1 ) ; } inline struct timeval tvMake( time_t sec, suseconds_t usec ) { struct timeval t; t.tv_sec = sec; t.tv_usec = usec; return( t ); } typedef std::chrono::microseconds Microseconds; typedef std::chrono::milliseconds Milliseconds; typedef std::chrono::seconds Seconds; typedef std::chrono::minutes Minutes; typedef std::chrono::hours Hours; typedef std::chrono::steady_clock::time_point TimePoint; typedef std::chrono::system_clock::time_point SystemTimePoint; namespace zm { namespace chrono { namespace impl { template struct posix_duration_cast; // chrono -> timeval caster template struct posix_duration_cast, timeval> { static timeval cast(std::chrono::duration const &d) { timeval tv = {}; Seconds const sec = std::chrono::duration_cast(d); tv.tv_sec = sec.count(); tv.tv_usec = std::chrono::duration_cast(d - sec).count(); return tv; } }; // timeval -> chrono caster template struct posix_duration_cast> { static std::chrono::duration cast(timeval const &tv) { return std::chrono::duration_cast>( Seconds(tv.tv_sec) + Microseconds(tv.tv_usec) ); } }; // chrono -> DeltaTimeval caster template struct posix_duration_cast, DeltaTimeval> { template static DeltaTimeval cast(std::chrono::duration const &d) { typedef std::chrono::duration> fsec_t; DeltaTimeval res = {}; Seconds secs = std::chrono::duration_cast(d); fsec_t fsec = std::chrono::duration_cast>(d - secs); res.positive = fsec >= Seconds::zero(); res.delta = abs((secs + fsec).count()); res.sec = secs.count(); res.fsec = fsec.count(); res.prec = Prec; return res; } }; } // chrono -> timeval template auto duration_cast(std::chrono::duration const &d) -> typename std::enable_if::value, timeval>::type { return impl::posix_duration_cast, timeval>::cast(d); } // timeval -> chrono template Duration duration_cast(timeval const &tv) { return impl::posix_duration_cast::cast(tv); } // chrono -> DeltaTimeval template auto duration_cast(std::chrono::duration const &d) -> typename std::enable_if::value, DeltaTimeval>::type { return impl::posix_duration_cast, DeltaTimeval>::template cast(d); } } } #endif // ZM_TIME_H