added C callable API

This commit is contained in:
Jeff Hill
1999-12-14 21:19:38 +00:00
parent a24415f0c9
commit 8b7d1425e5
2 changed files with 590 additions and 210 deletions
+354 -83
View File
@@ -33,7 +33,6 @@
#define epicsExportSharedSymbols
#include "epicsAssert.h"
#include "tsDefs.h"
#include "envDefs.h"
#include "osiTime.h"
@@ -63,6 +62,18 @@ const unsigned osiTime::secPerMin = 60u;
struct tm *gmtime_r (const time_t *, struct tm *);
struct tm *localtime_r (const time_t *, struct tm *);
#endif
#if 0
struct TS_STAMP {
epicsUInt32 secPastEpoch; /* seconds since 0000 Jan 1, 1990 */
epicsUInt32 nsec; /* nanoseconds within second */
};
#endif
static const unsigned ntpEpochYear = 1900;
static const unsigned ntpEpocMonth = 0; // January
static const unsigned ntpEpocDayOfTheMonth = 1; // the 1st day of the month
static const long double ULONG_MAX_PLUS_ONE = (static_cast<long double>(ULONG_MAX) + 1.0);
//
// force this module to include code that can convert
@@ -76,6 +87,7 @@ public:
};
static const unsigned tmStructEpochYear = 1900;
static const unsigned epicsEpochYear = 1990;
static const unsigned epicsEpocMonth = 0; // January
static const unsigned epicsEpocDayOfTheMonth = 1; // the 1st day of the month
@@ -83,20 +95,10 @@ static const unsigned epicsEpocDayOfTheMonth = 1; // the 1st day of the month
//
// osiTime (const unsigned long secIn, const unsigned long nSecIn)
//
osiTime::osiTime (const unsigned long secIn, const unsigned long nSecIn)
inline osiTime::osiTime (const unsigned long secIn, const unsigned long nSecIn)
{
if (nSecIn<nSecPerSec) {
this->sec = secIn;
this->nSec = nSecIn;
}
else if (nSecIn<(nSecPerSec*2)){
this->sec = secIn + 1u;
this->nSec = nSecIn-nSecPerSec;
}
else {
this->sec = nSecIn/nSecPerSec + secIn;
this->nSec = nSecIn%nSecPerSec;
}
this->sec = nSecIn/nSecPerSec + secIn;
this->nSec = nSecIn%nSecPerSec;
}
//
@@ -128,8 +130,11 @@ class loadTimeInit {
public:
loadTimeInit ();
long epicsEpochOffset; // integer seconds
long double time_tTicksPerSec;
long double epicsEpochOffset; // seconds
#ifdef NTP_SUPPORT
long double ntpEpochOffset; // seconds
#endif
long double time_tSecPerTick; // seconds (both NTP and EPICS use int sec)
};
static const loadTimeInit lti;
@@ -139,7 +144,8 @@ static const loadTimeInit lti;
//
loadTimeInit::loadTimeInit ()
{
long secWest;
static const time_t ansiEpoch = 0;
long double secWest;
{
time_t current = time (NULL);
@@ -148,19 +154,19 @@ loadTimeInit::loadTimeInit ()
gmtime_r (&current, &date);
error = mktime (&date);
secWest = static_cast<long> (difftime (error, current));
assert (error!=(time_t)-1);
secWest = difftime (error, current);
}
{
time_t first = static_cast<time_t> (0);
time_t last = static_cast<time_t> (1);
this->time_tTicksPerSec = 1.0 / difftime (last, first);
this->time_tSecPerTick = difftime (last, first);
}
{
struct tm tmEpicsEpoch;
time_t epicsEpoch;
time_t ansiEpoch = 0;
tmEpicsEpoch.tm_sec = 0;
tmEpicsEpoch.tm_min = 0;
@@ -171,35 +177,88 @@ loadTimeInit::loadTimeInit ()
tmEpicsEpoch.tm_isdst = -1; // dont know if its daylight savings time
epicsEpoch = mktime (&tmEpicsEpoch);
//
// when this happens we will need to write the code which
// subtract the tm structures ourselves
//
assert (epicsEpoch!=(time_t)-1);
this->epicsEpochOffset = static_cast<long> (difftime (epicsEpoch, ansiEpoch));
this->epicsEpochOffset -= secWest;
this->epicsEpochOffset = difftime (epicsEpoch, ansiEpoch) - secWest;
}
#ifdef NTP_SUPPORT
/* unfortunately, on NT mktime cant calculate a time_t for a date before 1970 */
{
struct tm tmEpochNTP;
time_t ntpEpoch;
tmEpochNTP.tm_sec = 0;
tmEpochNTP.tm_min = 0;
tmEpochNTP.tm_hour = 0;
tmEpochNTP.tm_mday = ntpEpocDayOfTheMonth;
tmEpochNTP.tm_mon = ntpEpocMonth;
tmEpochNTP.tm_year = ntpEpochYear-tmStructEpochYear;
tmEpochNTP.tm_isdst = -1; // dont know if its daylight savings time
ntpEpoch = mktime (&tmEpochNTP);
assert (ntpEpoch!=(time_t)-1);
this->ntpEpochOffset = static_cast<long> (difftime (ansiEpoch, ntpEpoch) + this->epicsEpochOffset - secWest);
}
#endif
}
//
// ansiSecToInternalSec ()
// osiTime::addNanoSec ()
//
unsigned long osiTime::time_tToInternalSec (const time_t &ansiTimeTicks)
// many of the UNIX timestamp formats have nano sec stored as a long
//
inline void osiTime::addNanoSec (long nSecAdj)
{
unsigned long sec;
//
// for now assume that they dont allow negative nanoseconds
// on UNIX platforms (this could be a mistake)
//
if ( nSecAdj < 0 ) {
throw negNanoSecInTimeStampFromUNIX ();
}
sec = static_cast<unsigned long> (ansiTimeTicks / lti.time_tTicksPerSec);
unsigned long offset = static_cast<unsigned long> (nSecAdj);
// expect over / under flow
if (lti.epicsEpochOffset>=0) {
sec -= static_cast<unsigned long>(lti.epicsEpochOffset);
}
else {
sec += static_cast<unsigned long>(-lti.epicsEpochOffset);
}
if ( offset >= nSecPerSec ) {
throw nanoSecFieldIsTooLarge ();
}
return sec;
//
// no need to worry about overflow here because
// offset + this->nSec will be less than ULONG_MAX/2
//
*this = osiTime (this->sec, this->nSec + offset);
}
//
// osiTime (const time_t_wrapper &tv)
//
osiTime::osiTime (const time_t_wrapper &ansiTimeTicks)
{
static long double uLongMax = static_cast<long double>(ULONG_MAX);
long double sec;
//
// map time_t, which ansi C defines as some arithmetic type, into "long double"
//
sec = ansiTimeTicks.ts * lti.time_tSecPerTick - lti.epicsEpochOffset;
//
// map into the the EPICS time stamp range (which allows rollover)
//
if (sec < 0.0) {
if (sec < -uLongMax) {
sec = sec + static_cast<unsigned long>(-sec/uLongMax)*uLongMax;
}
sec += uLongMax;
}
else if (sec > uLongMax) {
sec = sec - static_cast<unsigned long>(sec/uLongMax)*uLongMax;
}
this->sec = static_cast <unsigned long> (sec);
this->nSec = static_cast <unsigned long> ( (sec-this->sec) * nSecPerSec );
}
//
@@ -208,19 +267,16 @@ unsigned long osiTime::time_tToInternalSec (const time_t &ansiTimeTicks)
osiTime::operator time_t_wrapper () const
{
long double tmp;
unsigned long newSec;
time_t_wrapper wrap;
// expect over/under flow and allow it to occur befor proceeding
if (lti.epicsEpochOffset>=0) {
newSec = this->sec + static_cast<unsigned long>(lti.epicsEpochOffset);
}
else {
newSec = this->sec + static_cast<unsigned long>(-lti.epicsEpochOffset);
}
tmp = newSec * lti.time_tTicksPerSec;
tmp += (this->nSec * lti.time_tTicksPerSec) / nSecPerSec;
wrap.ts = static_cast<time_t> (tmp);
tmp = (this->sec + lti.epicsEpochOffset) / lti.time_tSecPerTick;
tmp += (this->nSec / lti.time_tSecPerTick) / nSecPerSec;
//
// map "long double" into time_t which ansi C defines as some arithmetic type
//
wrap.ts = static_cast <time_t> (tmp);
return wrap;
}
@@ -229,32 +285,43 @@ osiTime::operator time_t_wrapper () const
//
osiTime::operator tm_nano_sec () const
{
struct tm_nano_sec tm;
tm_nano_sec tm;
time_t_wrapper ansiTimeTicks;
struct tm *p;
ansiTimeTicks = *this;
// from POSIX RT
localtime_r (&ansiTimeTicks.ts, &tm.ansi_tm);
// reentrant version of localtime() - from POSIX RT
// WRS prototype is incorrect ?
p = localtime_r (&ansiTimeTicks.ts, &tm.ansi_tm);
if (p != &tm.ansi_tm) {
throw internalFailure ();
}
tm.nsec = this->nSec;
tm.nSec = this->nSec;
return tm;
}
//
// osiTime (const struct tm_nano_sec &tm)
// osiTime (const tm_nano_sec &tm)
//
osiTime::osiTime (const struct tm_nano_sec &tm)
osiTime::osiTime (const tm_nano_sec &tm)
{
time_t ansiTimeTicks;
time_t_wrapper ansiTimeTicks;
struct tm tmp = tm.ansi_tm;
ansiTimeTicks = mktime (&tmp);
assert (ansiTimeTicks!=(time_t)-1);
ansiTimeTicks.ts = mktime (&tmp);
if (ansiTimeTicks.ts==(time_t)-1) {
throw formatProblemWithStructTM ();
}
this->sec = osiTime::time_tToInternalSec (ansiTimeTicks);
this->nSec = tm.nsec;
*this = osiTime (ansiTimeTicks);
if (tm.nSec>=nSecPerSec) {
throw nanoSecFieldIsTooLarge ();
}
*this = osiTime (this->sec, this->nSec + tm.nSec);
}
//
@@ -276,16 +343,37 @@ osiTime::operator struct timespec () const
//
osiTime::osiTime (const struct timespec &ts)
{
this->sec = osiTime::time_tToInternalSec (ts.tv_sec);
assert (ts.tv_nsec>=0);
unsigned long nSecIn = static_cast<unsigned long> (ts.tv_nsec);
if (nSecIn<nSecPerSec) {
this->nSec = nSecIn;
}
else {
this->sec += nSecIn / nSecPerSec;
this->nSec = nSecIn % nSecPerSec;
}
time_t_wrapper ansiTimeTicks;
ansiTimeTicks.ts = ts.tv_sec;
*this = osiTime (ansiTimeTicks);
this->addNanoSec (ts.tv_nsec);
}
//
// operator struct timeval ()
//
osiTime::operator struct timeval () const
{
struct timeval ts;
time_t_wrapper ansiTimeTicks;
ansiTimeTicks = *this;
ts.tv_sec = ansiTimeTicks.ts;
ts.tv_usec = static_cast<long> (this->nSec / nSecPerUSec);
return ts;
}
//
// osiTime (const struct timeval &ts)
//
osiTime::osiTime (const struct timeval &ts)
{
time_t_wrapper ansiTimeTicks;
ansiTimeTicks.ts = ts.tv_sec;
*this = osiTime (ansiTimeTicks);
this->addNanoSec (ts.tv_usec * nSecPerUSec);
}
//
@@ -307,15 +395,15 @@ osiTime::operator aitTimeStamp () const
//
osiTime::osiTime (const aitTimeStamp &ts)
{
this->sec = osiTime::time_tToInternalSec (ts.tv_sec);
time_t_wrapper ansiTimeTicks;
if (ts.tv_nsec<nSecPerSec) {
this->nSec = ts.tv_nsec;
}
else {
this->sec += ts.tv_nsec / nSecPerSec;
this->nSec = ts.tv_nsec % nSecPerSec;
}
ansiTimeTicks.ts = ts.tv_sec;
*this = osiTime (ansiTimeTicks);
if ( ts.tv_nsec>=nSecPerSec ) {
throw nanoSecFieldIsTooLarge ();
}
*this = osiTime ( this->sec, this->nSec + ts.tv_nsec );
}
//
@@ -338,6 +426,53 @@ osiTime::osiTime (const struct TS_STAMP &ts)
this->nSec = ts.nsec;
}
//
// osiTime::ntpTimeStamp ()
//
#ifdef NTP_SUPPORT
osiTime::operator ntpTimeStamp () const
{
ntpTimeStamp ts;
if (lti.ntpEpochOffset>=0) {
unsigned long offset = static_cast<unsigned long> (lti.ntpEpochOffset);
// underflow expected
ts.l_ui = this->sec - offset;
}
else {
unsigned long offset = static_cast<unsigned long> (-lti.ntpEpochOffset);
// overflow expected
ts.l_ui = this->sec + offset;
}
ts.l_uf = static_cast<unsigned long> ( ( this->nSec * ULONG_MAX_PLUS_ONE ) / nSecPerSec );
return ts;
}
#endif
//
// osiTime::osiTime (const ntpTimeStamp &ts)
//
#ifdef NTP_SUPPORT
osiTime::osiTime (const ntpTimeStamp &ts)
{
if (lti.ntpEpochOffset>=0) {
unsigned long offset = static_cast<unsigned long> (lti.ntpEpochOffset);
// overflow expected
this->sec = ts.l_ui + this->sec + offset;
}
else {
unsigned long offset = static_cast<unsigned long> (-lti.ntpEpochOffset);
// underflow expected
this->sec = ts.l_ui + this->sec - offset;
}
this->nSec = static_cast<unsigned long> ( ( ts.l_uf / ULONG_MAX_PLUS_ONE ) * nSecPerSec );
}
#endif
//
// osiTime::show (unsigned)
//
@@ -349,8 +484,8 @@ void osiTime::show (unsigned) const
status = strftime (bigBuffer, sizeof(bigBuffer), "%a %b %d %H:%M:%S %Y", &tmns.ansi_tm);
if (status>0) {
printf ("osiTime: %s %f\n", bigBuffer,
static_cast <double> (tmns.nsec) / nSecPerSec);
printf ("osiTime: %s %g\n", bigBuffer,
static_cast <double> (tmns.nSec) / nSecPerSec);
}
}
@@ -366,7 +501,7 @@ osiTime osiTime::operator + (const long double &rhs) const
if (rhs >= 0) {
secOffset = static_cast <unsigned long> (rhs);
fnsec = rhs - static_cast <long double> (secOffset);
fnsec = rhs - secOffset;
nSecOffset = static_cast <unsigned long> (fnsec * nSecPerSec);
newSec = this->sec + secOffset; // overflow expected
@@ -378,7 +513,7 @@ osiTime osiTime::operator + (const long double &rhs) const
}
else {
secOffset = static_cast <unsigned long> (-rhs);
fnsec = rhs + static_cast <long double> (secOffset);
fnsec = rhs + secOffset;
nSecOffset = static_cast <unsigned long> (-fnsec * nSecPerSec);
newSec = this->sec - secOffset; // underflow expected
@@ -568,3 +703,139 @@ bool osiTime::operator < (const osiTime &rhs) const
return rc;
}
extern "C" {
/*
* ANSI C interface
*
* its too bad that these cant be implemented with inline functions
* at least when running the GNU compiler
*/
epicsShareFunc void osiTimeGetCurrent (osiTime *pDest)
{
*pDest = osiTime::getCurrent();
}
epicsShareFunc void osiTimeSynchronize ()
{
osiTime::synchronize ();
}
epicsShareFunc int osiTimeToTS_STAMP (TS_STAMP *pDest, const osiTime *pSrc)
{
try {
*pDest = *pSrc;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc int osiTimeFromTS_STAMP (osiTime *pDest, const TS_STAMP *pSrc)
{
try {
*pDest = *pSrc;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc int osiTimeToTime_t (time_t *pDest, const osiTime *pSrc)
{
try {
time_t_wrapper dst;
dst = *pSrc;
*pDest = dst.ts;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc int osiTimeFromTime_t (osiTime *pDest, time_t src)
{
try {
time_t_wrapper dst;
dst.ts = src;
*pDest = dst;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc int osiTimeToTM (tm_nano_sec *pDest, const osiTime *pSrc)
{
try {
*pDest = *pSrc;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc int osiTimeFromTM (osiTime *pDest, const tm_nano_sec *pSrc)
{
try {
*pDest = *pSrc;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc int osiTimeToTimespec (struct timespec *pDest, const osiTime *pSrc)
{
try {
*pDest = *pSrc;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc int osiTimeFromTimespec (osiTime *pDest, const struct timespec *pSrc)
{
try {
*pDest = *pSrc;
}
catch (...) {
return -1;
}
return 0;
}
epicsShareFunc long double osiTimeDiffInSeconds (const osiTime *pLeft, const osiTime *pRight)
{
return *pLeft - *pRight;
}
epicsShareFunc void osiTimeAddSeconds (osiTime *pDest, long double seconds)
{
*pDest += seconds;
}
epicsShareFunc int osiTimeEqual (const osiTime *pLeft, const osiTime *pRight)
{
return *pLeft == *pRight;
}
epicsShareFunc int osiTimeNotEqual (const osiTime *pLeft, const osiTime *pRight)
{
return *pLeft != *pRight;
}
epicsShareFunc int osiTimeLessThan (const osiTime *pLeft, const osiTime *pRight)
{
return *pLeft < *pRight;
}
epicsShareFunc int osiTimeLessThanEqual (const osiTime *pLeft, const osiTime *pRight)
{
return *pLeft <= *pRight;
}
epicsShareFunc int osiTimeGreaterThan (const osiTime *pLeft, const osiTime *pRight)
{
return *pLeft > *pRight;
}
epicsShareFunc int osiTimeGreaterThanEqual (const osiTime *pLeft, const osiTime *pRight)
{
return *pLeft >= *pRight;
}
epicsShareFunc void osiTimeShow (const osiTime *pTS, unsigned interestLevel)
{
pTS->show (interestLevel);
}
}
+236 -127
View File
@@ -32,118 +32,179 @@
#ifndef osiTimehInclude
#define osiTimehInclude
//
// ANSI C
//
/*
* ANSI C
*/
#include <time.h>
#include "shareLib.h"
#include "tsDefs.h"
#include "epicsTypes.h"
struct TS_STAMP; // EPICS
class aitTimeStamp; // GDD
struct timespec; // POSIX real time
struct TS_STAMP; /* EPICS */
struct timespec; /* POSIX real time */
struct timeval; /* BSD */
#ifdef __cplusplus
class aitTimeStamp; /* GDD */
#endif
//
// an extended ANSI C RTL "struct tm" which includes nano seconds.
//
struct tm_nano_sec {
tm ansi_tm; // ANSI C time details
unsigned long nsec; // nano seconds extension
};
/*
* an extended ANSI C RTL "struct tm" which includes nano seconds.
*/
typedef struct tm_nano_sec {
struct tm ansi_tm; /* ANSI C time details */
unsigned long nSec; /* nano seconds extension */
} tm_nano_sec;
//
// 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 {
/*
* wrapping this in a struct allows conversion to and
* from ANSI time_t but does not allow unexpected
* conversions to occur
*/
typedef struct time_t_wrapper {
time_t ts;
};
} time_t_wrapper;
//
// class osiTime
//
// high resolution osiTime stamp
//
class epicsShareClass osiTime {
public:
/*
* NTP uses two fixed point formats. The first (l_fp) is the "long"
* format and is 64 bits long with the decimal between bits 31 and 32.
* This is used for time stamps in the NTP packet header (in network
* byte order) and for internal computations of offsets (in local host
* byte order). We use the same structure for both signed and unsigned
* values, which is a big hack but saves rewriting all the operators
* twice. Just to confuse this, we also sometimes just carry the
* fractional part in calculations, in both signed and unsigned forms.
* Anyway, an l_fp looks like:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Integral Part |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Fractional Part |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
typedef struct {
epicsUInt32 l_ui; /* sec past NTP epoch */
epicsUInt32 l_uf; /* fractional seconds */
}ntpTimeStamp;
//
// fetch the current time
//
/*
* The number of nanoseconds past 0000 Jan 1, 1990, GMT (or UTC, if you prefer).
*/
typedef struct TS_STAMP {
epicsUInt32 secPastEpoch; /* seconds since 0000 Jan 1, 1990 */
epicsUInt32 nsec; /* nanoseconds within second */
} TS_STAMP;
/*
* type osiTime
*
* high resolution osiTime stamp class (struct) which can be used
* from both C++ and also from ANSI C
*/
typedef struct epicsShareClass osiTime
{
#ifdef __cplusplus
/*
* exceptions
*/
class unableToFetchCurrentTime {};
class negNanoSecInTimeStampFromUNIX {};
class nanoSecFieldIsTooLarge {};
class formatProblemWithStructTM {};
class internalFailure {};
/*
* fetch the current time
*/
static osiTime getCurrent();
//
// some systems have a high resolution time source which
// gradually drifts away from the master time base. Calling
// this routine will cause class "time" to realign the high
// resolution result from getCurrent() with some master
// time base.
//
// if this routine has not been called at least once so far
// by the current process then it is called the first time
// that getCurrent() is called
//
/*
* some systems have a high resolution time source which
* gradually drifts away from the master time base. Calling
* this routine will cause class "time" to realign the high
* resolution result from getCurrent() with some master
* time base.
*
* if this routine has not been called at least once so far
* by the current process then it is called the first time
* that getCurrent() is called
*/
static void synchronize();
//
// create an osiTime for the EPICS epoch
//
/*
* create an osiTime for the EPICS epoch
*/
osiTime ();
osiTime (const osiTime &t);
//
// convert to and from EPICS TS_STAMP format
//
/*
* convert to and from EPICS TS_STAMP format
*/
operator struct TS_STAMP () const;
osiTime (const struct TS_STAMP &ts);
osiTime operator = (const struct TS_STAMP &rhs);
//
// convert to and from ANSI C's "time_t"
//
// "time_t" is wrapped in another structure to avoid
// unsuspected type conversions
// fetch value as an integer
//
/*
* convert to and from ANSI C's "time_t"
*
* "time_t" is wrapped in another structure to avoid
* unsuspected type conversions
* fetch value as an integer
*/
operator time_t_wrapper () const;
osiTime (const time_t_wrapper &tv);
osiTime operator = (const time_t_wrapper &rhs);
//
// convert to and from ANSI C's "struct tm" (with nano seconds)
//
operator struct tm_nano_sec () const;
osiTime (const struct tm_nano_sec &ts);
osiTime operator = (const struct tm_nano_sec &rhs);
/*
* convert to and from ANSI C's "struct tm" (with nano seconds)
*/
operator tm_nano_sec () const;
osiTime (const tm_nano_sec &ts);
osiTime operator = (const tm_nano_sec &rhs);
//
// convert to and from POSIX RT's "struct timespec"
//
/*
* convert to and from POSIX RT's "struct timespec"
*/
operator struct timespec () const;
osiTime (const struct timespec &ts);
osiTime operator = (const struct timespec &rhs);
//
// convert to and from GDD's aitTimeStamp format
//
/*
* convert to and from BSD's "struct timeval"
*/
operator struct timeval () const;
osiTime (const struct timeval &ts);
osiTime operator = (const struct timeval &rhs);
/*
* convert to and from NTP timestamp format
*/
operator ntpTimeStamp () const;
osiTime (const ntpTimeStamp &ts);
osiTime operator = (const ntpTimeStamp &rhs);
/*
* convert to and from GDD's aitTimeStamp format
*/
operator aitTimeStamp () const;
osiTime (const aitTimeStamp &ts);
osiTime operator = (const aitTimeStamp &rhs);
//
// arithmetic operators
//
/*
* arithmetic operators
*/
long double operator- (const osiTime &rhs) const; // returns seconds
osiTime operator+ (const long double &rhs) const; // add rhs seconds
osiTime operator- (const long double &rhs) const; // subtract rhs seconds
osiTime operator+= (const long double &rhs); // add rhs seconds
osiTime operator-= (const long double &rhs); // subtract rhs seconds
//
// comparison operators
//
/*
* comparison operators
*/
bool operator == (const osiTime &rhs) const;
bool operator != (const osiTime &rhs) const;
bool operator <= (const osiTime &rhs) const;
@@ -151,14 +212,14 @@ public:
bool operator >= (const osiTime &rhs) const;
bool operator > (const osiTime &rhs) const;
//
// dump current state to standard out
//
/*
* dump current state to standard out
*/
void show (unsigned interestLevel) const;
//
// useful public constants
//
/*
* useful public constants
*/
static const unsigned secPerMin;
static const unsigned mSecPerSec;
static const unsigned uSecPerSec;
@@ -166,28 +227,98 @@ public:
static const unsigned nSecPerUSec;
private:
unsigned long sec; /* seconds since O000 Jan 1, 1990 */
unsigned long nSec; /* nanoseconds within second */
static osiTime osdGetCurrent();
static unsigned long time_tToInternalSec (const time_t &tv);
//
// 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)
//
/*
* 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)
*/
osiTime (const unsigned long sec, const unsigned long nSec);
};
void addNanoSec (long nanoSecAdjust);
/////////////////////////////////////
//
// time inline member functions
//
/////////////////////////////////////
#endif /* ifdef __cplusplus */
/*
* private - do not touch these from within C programs
*/
unsigned long sec; /* seconds since O000 Jan 1, 1990 */
unsigned long nSec; /* nanoseconds within second */
} osiTime;
/*
* ANSI C interface to osiTime
*
* all conversion functions return -1 on failure and 0 on success
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* fetch and synchronize the current time
*/
epicsShareFunc void osiTimeGetCurrent (osiTime *pDest);
epicsShareFunc void osiTimeSynchronize ();
/*
* convert to and from EPICS TS_STAMP format
*/
epicsShareFunc int osiTimeToTS_STAMP (TS_STAMP *pDest, const osiTime *pSrc);
epicsShareFunc int osiTimeFromTS_STAMP (osiTime *pDest, const TS_STAMP *pSrc);
/*
* convert to and from ANSI C's "time_t"
*/
epicsShareFunc int osiTimeToTime_t (time_t *pDest, const osiTime *pSrc);
epicsShareFunc int osiTimeFromTime_t (osiTime *pDest, time_t src);
/*
* convert to and from ANSI C's "struct tm" (with nano seconds)
*/
epicsShareFunc int osiTimeToTM (tm_nano_sec *pDest, const osiTime *pSrc);
epicsShareFunc int osiTimeFromTM (osiTime *pDest, const tm_nano_sec *pSrc);
/*
* convert to and from POSIX RT's "struct timespec"
*/
epicsShareFunc int osiTimeToTimespec (struct timespec *pDest, const osiTime *pSrc);
epicsShareFunc int osiTimeFromTimespec (osiTime *pDest, const struct timespec *pSrc);
/*
* arithmetic operations
*/
epicsShareFunc long double osiTimeDiffInSeconds (const osiTime *pLeft, const osiTime *pRight); /* returns *pLeft - *pRight in seconds */
epicsShareFunc void osiTimeAddSeconds (osiTime *pDest, long double secondsToAdd); /* adds seconds to *pLeft */
/*
* comparison operations
*/
epicsShareFunc int osiTimeEqual (const osiTime *pLeft, const osiTime *pRight); /* returns boolean result */
epicsShareFunc int osiTimeNotEqual (const osiTime *pLeft, const osiTime *pRight); /* returns boolean result */
epicsShareFunc int osiTimeLessThan (const osiTime *pLeft, const osiTime *pRight); /* returns boolean result (true if *pLeft < *pRight) */
epicsShareFunc int osiTimeLessThanEqual (const osiTime *pLeft, const osiTime *pRight); /* returns boolean result (true if *pLeft <= *pRight) */
epicsShareFunc int osiTimeGreaterThan (const osiTime *pLeft, const osiTime *pRight); /* returns boolean result (true if *pLeft > *pRight) */
epicsShareFunc int osiTimeGreaterThanEqual (const osiTime *pLeft, const osiTime *pRight); /* returns boolean result (true if *pLeft >= *pRight) */
/*
* dump current state to standard out
*/
epicsShareFunc void osiTimeShow (const osiTime *, unsigned interestLevel);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
/*
* type osiTime inline member functions
*/
inline osiTime::osiTime () : sec(0u), nSec(0u) {}
@@ -220,81 +351,59 @@ inline bool osiTime::operator == (const osiTime &rhs) const
}
}
//
// operator !=
//
inline bool osiTime::operator != (const osiTime &rhs) const
{
return !osiTime::operator == (rhs);
}
//
// operator >= (const osiTime &lhs, const osiTime &rhs)
//
inline bool osiTime::operator >= (const osiTime &rhs) const
{
return !(*this < rhs);
}
//
// operator > (const osiTime &lhs, const osiTime &rhs)
//
inline bool osiTime::operator > (const osiTime &rhs) const
{
return !(*this <= rhs);
}
//
// osiTime operator = (const struct tm_nano_sec &rhs)
//
inline osiTime osiTime::operator = (const struct tm_nano_sec &rhs)
inline osiTime osiTime::operator = (const tm_nano_sec &rhs)
{
return *this = osiTime (rhs);
}
//
// operator = (const struct timespec &rhs)
//
inline osiTime osiTime::operator = (const struct timespec &rhs)
{
*this = osiTime (rhs);
return *this;
}
//
// operator = (const aitTimeStamp &rhs)
//
inline osiTime osiTime::operator = (const aitTimeStamp &rhs)
{
*this = osiTime (rhs);
return *this;
}
inline osiTime osiTime::operator = (const struct TS_STAMP &rhs)
{
*this = osiTime (rhs);
return *this;
}
//
// osiTime (const time_t_wrapper &tv)
//
inline osiTime::osiTime (const time_t_wrapper &ansiTimeTicks)
#ifdef NTP_SUPPORT
inline osiTime osiTime::operator = (const ntpTimeStamp &rhs)
{
this->sec = osiTime::time_tToInternalSec (ansiTimeTicks.ts);
this->nSec = 0;
*this = osiTime (rhs);
return *this;
}
#endif
//
// osiTime operator = (const time_t_wrapper &rhs)
// operator >= (const osiTime &lhs, const osiTime &rhs)
//
inline osiTime osiTime::operator = (const time_t_wrapper &rhs)
{
*this = osiTime (rhs);
return *this;
}
#endif // osiTimehInclude
#endif /* __cplusplus */
#endif /* osiTimehInclude */