zoneminder/src/zm_time.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

273 lines
7.1 KiB
C
Raw Normal View History

//
// 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 <chrono>
#include <sys/time.h>
// 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
2020-11-02 05:11:19 +08:00
/*
extern struct timeval tv;
2020-11-02 05:11:19 +08:00
*/
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<typename From, typename To>
struct posix_duration_cast;
// chrono -> timeval caster
template<typename Rep, typename Period>
struct posix_duration_cast<std::chrono::duration<Rep, Period>, timeval> {
static timeval cast(std::chrono::duration<Rep, Period> const &d) {
timeval tv = {};
Seconds const sec = std::chrono::duration_cast<Seconds>(d);
tv.tv_sec = sec.count();
tv.tv_usec = std::chrono::duration_cast<Microseconds>(d - sec).count();
return tv;
}
};
// timeval -> chrono caster
template<typename Rep, typename Period>
struct posix_duration_cast<timeval, std::chrono::duration<Rep, Period>> {
static std::chrono::duration<Rep, Period> cast(timeval const &tv) {
return std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
Seconds(tv.tv_sec) + Microseconds(tv.tv_usec)
);
}
};
// chrono -> DeltaTimeval caster
template<typename Rep, typename Period>
struct posix_duration_cast<std::chrono::duration<Rep, Period>, DeltaTimeval> {
template<uint32 Prec>
static DeltaTimeval cast(std::chrono::duration<Rep, Period> const &d) {
typedef std::chrono::duration<int64, std::ratio<1, Prec>> fsec_t;
DeltaTimeval res = {};
Seconds secs = std::chrono::duration_cast<Seconds>(d);
fsec_t fsec = std::chrono::duration_cast<fsec_t, int64, std::ratio<1, Prec>>(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<typename T, typename Rep, typename Period>
auto duration_cast(std::chrono::duration<Rep, Period> const &d)
-> typename std::enable_if<std::is_same<T, timeval>::value, timeval>::type {
return impl::posix_duration_cast<std::chrono::duration<Rep, Period>, timeval>::cast(d);
}
// timeval -> chrono
template<typename Duration>
Duration duration_cast(timeval const &tv) {
return impl::posix_duration_cast<timeval, Duration>::cast(tv);
}
// chrono -> DeltaTimeval
template<typename T, uint32 Prec, typename Rep, typename Period>
auto duration_cast(std::chrono::duration<Rep, Period> const &d)
-> typename std::enable_if<std::is_same<T, DeltaTimeval>::value, DeltaTimeval>::type {
return impl::posix_duration_cast<std::chrono::duration<Rep, Period>, DeltaTimeval>::template cast<Prec>(d);
}
}
}
#endif // ZM_TIME_H