369 lines
12 KiB
C++
369 lines
12 KiB
C++
/*************************************************************************\
|
|
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
|
* National Laboratory.
|
|
* Copyright (c) 2002 The Regents of the University of California, as
|
|
* Operator of Los Alamos National Laboratory.
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
/* epicsTime.h */
|
|
/* Author Jeffrey O. Hill */
|
|
|
|
#ifndef epicsTimehInclude
|
|
#define epicsTimehInclude
|
|
|
|
#include <time.h>
|
|
|
|
#include "shareLib.h"
|
|
#include "epicsTypes.h"
|
|
#include "osdTime.h"
|
|
#include "errMdef.h"
|
|
|
|
/* The EPICS Epoch is 00:00:00 Jan 1, 1990 UTC */
|
|
#define POSIX_TIME_AT_EPICS_EPOCH 631152000u
|
|
|
|
/* epics time stamp for C interface*/
|
|
typedef struct epicsTimeStamp {
|
|
epicsUInt32 secPastEpoch; /* seconds since 0000 Jan 1, 1990 */
|
|
epicsUInt32 nsec; /* nanoseconds within second */
|
|
} epicsTimeStamp;
|
|
|
|
/*TS_STAMP is deprecated */
|
|
#define TS_STAMP epicsTimeStamp
|
|
|
|
|
|
struct timespec; /* POSIX real time */
|
|
struct timeval; /* BSD */
|
|
struct l_fp; /* NTP timestamp */
|
|
|
|
#ifdef __cplusplus
|
|
|
|
/*
|
|
* extend ANSI C RTL "struct tm" to include nano seconds within a second
|
|
* and a struct tm that is adjusted for the local timezone
|
|
*/
|
|
struct local_tm_nano_sec {
|
|
struct tm ansi_tm; /* ANSI C time details */
|
|
unsigned long nSec; /* nano seconds extension */
|
|
};
|
|
|
|
/*
|
|
* extend ANSI C RTL "struct tm" to includes nano seconds within a second
|
|
* and a struct tm that is adjusted for GMT (UTC)
|
|
*/
|
|
struct gm_tm_nano_sec {
|
|
struct tm ansi_tm; /* ANSI C time details */
|
|
unsigned long nSec; /* nano seconds extension */
|
|
};
|
|
|
|
/*
|
|
* wrapping this in a struct allows conversion to and
|
|
* from ANSI time_t but does not allow unexpected
|
|
* conversions to occur
|
|
*/
|
|
struct time_t_wrapper {
|
|
time_t ts;
|
|
};
|
|
|
|
class epicsShareClass epicsTimeEvent
|
|
{
|
|
public:
|
|
epicsTimeEvent (const int &number);
|
|
operator int () const;
|
|
private:
|
|
int eventNumber;
|
|
};
|
|
|
|
class epicsShareClass epicsTime
|
|
{
|
|
public:
|
|
/* exceptions */
|
|
class unableToFetchCurrentTime {};
|
|
class formatProblemWithStructTM {};
|
|
|
|
epicsTime ();
|
|
epicsTime ( const epicsTime & t );
|
|
|
|
static epicsTime getEvent ( const epicsTimeEvent & );
|
|
static epicsTime getCurrent ();
|
|
|
|
/* convert to and from EPICS epicsTimeStamp format */
|
|
operator epicsTimeStamp () const;
|
|
epicsTime ( const epicsTimeStamp & ts );
|
|
epicsTime & operator = ( const epicsTimeStamp & );
|
|
|
|
/* convert to and from ANSI time_t */
|
|
operator time_t_wrapper () const;
|
|
epicsTime ( const time_t_wrapper & );
|
|
epicsTime & operator = ( const time_t_wrapper & );
|
|
|
|
/*
|
|
* convert to and from ANSI Cs "struct tm" (with nano seconds)
|
|
* adjusted for the local time zone
|
|
*/
|
|
operator local_tm_nano_sec () const;
|
|
epicsTime ( const local_tm_nano_sec & );
|
|
epicsTime & operator = ( const local_tm_nano_sec & );
|
|
|
|
/*
|
|
* convert to and from ANSI Cs "struct tm" (with nano seconds)
|
|
* adjusted for GM time (UTC)
|
|
*/
|
|
operator gm_tm_nano_sec () const;
|
|
epicsTime ( const gm_tm_nano_sec & );
|
|
epicsTime & operator = ( const gm_tm_nano_sec & );
|
|
|
|
/* convert to and from POSIX RTs "struct timespec" */
|
|
operator struct timespec () const;
|
|
epicsTime ( const struct timespec & );
|
|
epicsTime & operator = ( const struct timespec & );
|
|
|
|
/* convert to and from BSDs "struct timeval" */
|
|
operator struct timeval () const;
|
|
epicsTime ( const struct timeval & );
|
|
epicsTime & operator = ( const struct timeval & );
|
|
|
|
/* convert to and from NTP timestamp format */
|
|
operator l_fp () const;
|
|
epicsTime ( const l_fp & );
|
|
epicsTime & operator = ( const l_fp & );
|
|
|
|
/* convert to and from WIN32s FILETIME (implemented only on WIN32) */
|
|
operator struct _FILETIME () const;
|
|
epicsTime ( const struct _FILETIME & );
|
|
epicsTime & operator = ( const struct _FILETIME & );
|
|
|
|
/* arithmetic operators */
|
|
double operator- ( const epicsTime & ) const; /* returns seconds */
|
|
epicsTime operator+ ( const double & ) const; /* add rhs seconds */
|
|
epicsTime operator- ( const double & ) const; /* subtract rhs seconds */
|
|
epicsTime operator+= ( const double & ); /* add rhs seconds */
|
|
epicsTime operator-= ( const double & ); /* subtract rhs seconds */
|
|
|
|
/* comparison operators */
|
|
bool operator == ( const epicsTime & ) const;
|
|
bool operator != ( const epicsTime & ) const;
|
|
bool operator <= ( const epicsTime & ) const;
|
|
bool operator < ( const epicsTime & ) const;
|
|
bool operator >= ( const epicsTime & ) const;
|
|
bool operator > ( const epicsTime & ) const;
|
|
|
|
/* convert current state to user-specified string */
|
|
size_t strftime ( char * pBuff, size_t bufLength, const char * pFormat ) const;
|
|
|
|
/* dump current state to standard out */
|
|
void show ( unsigned interestLevel ) const;
|
|
|
|
private:
|
|
/*
|
|
* private because:
|
|
* a) application does not break when EPICS epoch is changed
|
|
* b) no assumptions about internal storage or internal precision
|
|
* in the application
|
|
* c) it would be easy to forget which argument is nanoseconds
|
|
* and which argument is seconds (no help from compiler)
|
|
*/
|
|
epicsTime ( const unsigned long secPastEpoch, const unsigned long nSec );
|
|
void addNanoSec ( long nanoSecAdjust );
|
|
|
|
unsigned long secPastEpoch; /* seconds since O000 Jan 1, 1990 */
|
|
unsigned long nSec; /* nanoseconds within second */
|
|
};
|
|
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
/* epicsTime routines return S_time_ error status values */
|
|
#define epicsTimeOK 0
|
|
#define S_time_noProvider (M_time| 1) /*No time provider*/
|
|
#define S_time_badEvent (M_time| 2) /*Bad event number*/
|
|
#define S_time_badArgs (M_time| 3) /*Invalid arguments*/
|
|
#define S_time_noMemory (M_time| 4) /*Out of memory*/
|
|
#define S_time_unsynchronized (M_time| 5) /*Provider not synchronized*/
|
|
#define S_time_timezone (M_time| 6) /*Invalid timeone*/
|
|
#define S_time_conversion (M_time| 7) /*Time conversion error*/
|
|
|
|
/*Some special values for eventNumber*/
|
|
#define epicsTimeEventCurrentTime 0
|
|
#define epicsTimeEventBestTime -1
|
|
#define epicsTimeEventDeviceTime -2
|
|
|
|
/* These are implemented in the "generalTime" framework */
|
|
epicsShareFunc int epicsShareAPI epicsTimeGetCurrent ( epicsTimeStamp * pDest );
|
|
epicsShareFunc int epicsShareAPI epicsTimeGetEvent (
|
|
epicsTimeStamp *pDest, int eventNumber);
|
|
|
|
/* These are callable from an Interrupt Service Routine */
|
|
epicsShareFunc int epicsTimeGetCurrentInt(epicsTimeStamp *pDest);
|
|
epicsShareFunc int epicsTimeGetEventInt(epicsTimeStamp *pDest, int eventNumber);
|
|
|
|
/* convert to and from ANSI C's "time_t" */
|
|
epicsShareFunc int epicsShareAPI epicsTimeToTime_t (
|
|
time_t * pDest, const epicsTimeStamp * pSrc );
|
|
epicsShareFunc int epicsShareAPI epicsTimeFromTime_t (
|
|
epicsTimeStamp * pDest, time_t src );
|
|
|
|
/* convert to and from ANSI C's "struct tm" with nano seconds */
|
|
epicsShareFunc int epicsShareAPI epicsTimeToTM (
|
|
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
|
|
epicsShareFunc int epicsShareAPI epicsTimeToGMTM (
|
|
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
|
|
epicsShareFunc int epicsShareAPI epicsTimeFromTM (
|
|
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
|
|
epicsShareFunc int epicsShareAPI epicsTimeFromGMTM (
|
|
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
|
|
|
|
/* convert to and from POSIX RT's "struct timespec" */
|
|
epicsShareFunc int epicsShareAPI epicsTimeToTimespec (
|
|
struct timespec * pDest, const epicsTimeStamp * pSrc );
|
|
epicsShareFunc int epicsShareAPI epicsTimeFromTimespec (
|
|
epicsTimeStamp * pDest, const struct timespec * pSrc );
|
|
|
|
/* convert to and from BSD's "struct timeval" */
|
|
epicsShareFunc int epicsShareAPI epicsTimeToTimeval (
|
|
struct timeval * pDest, const epicsTimeStamp * pSrc );
|
|
epicsShareFunc int epicsShareAPI epicsTimeFromTimeval (
|
|
epicsTimeStamp * pDest, const struct timeval * pSrc );
|
|
|
|
/*arithmetic operations */
|
|
epicsShareFunc double epicsShareAPI epicsTimeDiffInSeconds (
|
|
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight );/* left - right */
|
|
epicsShareFunc void epicsShareAPI epicsTimeAddSeconds (
|
|
epicsTimeStamp * pDest, double secondsToAdd ); /* adds seconds to *pDest */
|
|
|
|
/*comparison operations: returns (0,1) if (false,true) */
|
|
epicsShareFunc int epicsShareAPI epicsTimeEqual (
|
|
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
|
|
epicsShareFunc int epicsShareAPI epicsTimeNotEqual (
|
|
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight);
|
|
epicsShareFunc int epicsShareAPI epicsTimeLessThan (
|
|
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left < right */
|
|
epicsShareFunc int epicsShareAPI epicsTimeLessThanEqual (
|
|
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left <= right) */
|
|
epicsShareFunc int epicsShareAPI epicsTimeGreaterThan (
|
|
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left > right */
|
|
epicsShareFunc int epicsShareAPI epicsTimeGreaterThanEqual (
|
|
const epicsTimeStamp * pLeft, const epicsTimeStamp * pRight); /*true if left >= right */
|
|
|
|
/*convert to ASCII string */
|
|
epicsShareFunc size_t epicsShareAPI epicsTimeToStrftime (
|
|
char * pBuff, size_t bufLength, const char * pFormat, const epicsTimeStamp * pTS );
|
|
|
|
/* dump current state to standard out */
|
|
epicsShareFunc void epicsShareAPI epicsTimeShow (
|
|
const epicsTimeStamp *, unsigned interestLevel );
|
|
|
|
/* OS dependent reentrant versions of the ANSI C interface because */
|
|
/* vxWorks gmtime_r interface does not match POSIX standards */
|
|
epicsShareFunc int epicsShareAPI epicsTime_localtime ( const time_t * clock, struct tm * result );
|
|
epicsShareFunc int epicsShareAPI epicsTime_gmtime ( const time_t * clock, struct tm * result );
|
|
|
|
/* Advertised monotonic counter resolution (may not be accurate).
|
|
* Minimum non-zero difference between two calls to epicsMonotonicGet()
|
|
*/
|
|
epicsShareFunc epicsUInt64 epicsMonotonicResolution(void);
|
|
/* Fetch monotonic counter, return is nano-seconds since an unspecified time */
|
|
epicsShareFunc epicsUInt64 epicsMonotonicGet(void);
|
|
|
|
#ifdef EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE
|
|
epicsShareFunc void osdMonotonicInit(void);
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
/* inline member functions ,*/
|
|
#ifdef __cplusplus
|
|
|
|
/* epicsTimeEvent */
|
|
|
|
inline epicsTimeEvent::epicsTimeEvent (const int &number) :
|
|
eventNumber(number) {}
|
|
|
|
inline epicsTimeEvent::operator int () const
|
|
{
|
|
return this->eventNumber;
|
|
}
|
|
|
|
|
|
/* epicsTime */
|
|
|
|
inline epicsTime epicsTime::operator - ( const double & rhs ) const
|
|
{
|
|
return epicsTime::operator + ( -rhs );
|
|
}
|
|
|
|
inline epicsTime epicsTime::operator += ( const double & rhs )
|
|
{
|
|
*this = epicsTime::operator + ( rhs );
|
|
return *this;
|
|
}
|
|
|
|
inline epicsTime epicsTime::operator -= ( const double & rhs )
|
|
{
|
|
*this = epicsTime::operator + ( -rhs );
|
|
return *this;
|
|
}
|
|
|
|
inline bool epicsTime::operator == ( const epicsTime & rhs ) const
|
|
{
|
|
if ( this->secPastEpoch == rhs.secPastEpoch && this->nSec == rhs.nSec ) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
inline bool epicsTime::operator != ( const epicsTime & rhs ) const
|
|
{
|
|
return !epicsTime::operator == ( rhs );
|
|
}
|
|
|
|
inline bool epicsTime::operator >= ( const epicsTime & rhs ) const
|
|
{
|
|
return ! ( *this < rhs );
|
|
}
|
|
|
|
inline bool epicsTime::operator > ( const epicsTime & rhs ) const
|
|
{
|
|
return ! ( *this <= rhs );
|
|
}
|
|
|
|
inline epicsTime & epicsTime::operator = ( const local_tm_nano_sec & rhs )
|
|
{
|
|
return *this = epicsTime ( rhs );
|
|
}
|
|
|
|
inline epicsTime & epicsTime::operator = ( const gm_tm_nano_sec & rhs )
|
|
{
|
|
return *this = epicsTime ( rhs );
|
|
}
|
|
|
|
inline epicsTime & epicsTime::operator = ( const struct timespec & rhs )
|
|
{
|
|
*this = epicsTime ( rhs );
|
|
return *this;
|
|
}
|
|
|
|
inline epicsTime & epicsTime::operator = ( const epicsTimeStamp & rhs )
|
|
{
|
|
*this = epicsTime ( rhs );
|
|
return *this;
|
|
}
|
|
|
|
inline epicsTime & epicsTime::operator = ( const l_fp & rhs )
|
|
{
|
|
*this = epicsTime ( rhs );
|
|
return *this;
|
|
}
|
|
|
|
inline epicsTime & epicsTime::operator = ( const time_t_wrapper & rhs )
|
|
{
|
|
*this = epicsTime ( rhs );
|
|
return *this;
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
#endif /* epicsTimehInclude */
|
|
|