diff --git a/src/libCom/osi/osiFindGlobalSymbol.h b/src/libCom/osi/osiFindGlobalSymbol.h new file mode 100644 index 000000000..8f22a5277 --- /dev/null +++ b/src/libCom/osi/osiFindGlobalSymbol.h @@ -0,0 +1,16 @@ +#ifndef osiFindGlobalSymbolh +#define osiFindGlobalSymbolh + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shareLib.h" + +epicsShareFunc void * epicsShareAPI osiFindGlobalSymbol(const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* osiFindGlobalSymbolh */ diff --git a/src/libCom/osi/osiInterrupt.h b/src/libCom/osi/osiInterrupt.h new file mode 100644 index 000000000..952b733c3 --- /dev/null +++ b/src/libCom/osi/osiInterrupt.h @@ -0,0 +1,21 @@ +#ifndef osiInterrupth +#define osiInterrupth + +/*THIS MAY BE A BIG PROBLEM */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shareLib.h" + +epicsShareFunc int epicsShareAPI interruptLock(); +epicsShareFunc void epicsShareAPI interruptUnlock(int key); +epicsShareFunc int epicsShareAPI interruptIsInterruptContext(); +epicsShareFunc void epicsShareAPI interruptContextMessage(const char *message); + +#ifdef __cplusplus +} +#endif + +#endif /* osiInterrupth */ diff --git a/src/libCom/osi/osiRing.h b/src/libCom/osi/osiRing.h new file mode 100644 index 000000000..696dd4b1e --- /dev/null +++ b/src/libCom/osi/osiRing.h @@ -0,0 +1,42 @@ +/*osiRing.h */ + +/* Author: Marty Kraimer Date: 15JUL99 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +#ifndef INCosiRingh +#define INCosiRingh + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shareLib.h" + +typedef void *ringId; + +epicsShareFunc ringId epicsShareAPI ringCreate(int nbytes); +epicsShareFunc void epicsShareAPI ringDelete(ringId id); +epicsShareFunc int epicsShareAPI ringGet(ringId id, char *value,int nbytes); +epicsShareFunc int epicsShareAPI ringPut(ringId id, char *value,int nbytes); +epicsShareFunc void epicsShareAPI ringFlush(ringId id); +epicsShareFunc int epicsShareAPI ringFreeBytes(ringId id); +epicsShareFunc int epicsShareAPI ringUsedBytes(ringId id); +epicsShareFunc int epicsShareAPI ringSize(ringId id); +epicsShareFunc int epicsShareAPI ringIsEmpty(ringId id); +epicsShareFunc int epicsShareAPI ringIsFull(ringId id); + +#ifdef __cplusplus +} +#endif + +/* NOTES + If there is only one writer it is not necessary to lock for put + If there is a single reader it is not necessary to lock for puts +*/ + +#endif /* INCosiRingh */ diff --git a/src/libCom/osi/osiSem.h b/src/libCom/osi/osiSem.h new file mode 100644 index 000000000..2e6e2ccc7 --- /dev/null +++ b/src/libCom/osi/osiSem.h @@ -0,0 +1,41 @@ +#ifndef osiSemh +#define osiSemh + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shareLib.h" + +typedef void *semId; +typedef enum {semTakeOK,semTakeTimeout,semTakeError} semTakeStatus; +typedef enum {semEmpty,semFull} semInitialState; + +epicsShareFunc semId epicsShareAPI semBinaryCreate(int initialState); +epicsShareFunc void epicsShareAPI semBinaryDestroy(semId id); +epicsShareFunc void epicsShareAPI semBinaryGive(semId id); +epicsShareFunc semTakeStatus epicsShareAPI semBinaryTake(semId id); +epicsShareFunc void epicsShareAPI semBinaryTakeAssert(semId id); +epicsShareFunc semTakeStatus epicsShareAPI semBinaryTakeTimeout(semId id, double timeOut); +epicsShareFunc semTakeStatus epicsShareAPI semBinaryTakeNoWait(semId id); +epicsShareFunc void epicsShareAPI semBinaryFlush(semId id); + +epicsShareFunc semId epicsShareAPI semMutexCreate(void); +epicsShareFunc void epicsShareAPI semMutexDestroy(semId id); +epicsShareFunc void epicsShareAPI semMutexGive(semId id); +epicsShareFunc semTakeStatus epicsShareAPI semMutexTake(semId id); +epicsShareFunc void epicsShareAPI semMutexTakeAssert(semId id); +epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeTimeout(semId id, double timeOut); +epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeNoWait(semId id); +epicsShareFunc void epicsShareAPI semMutexFlush(semId id); + +#ifdef __cplusplus +} +#endif + +/*NOTES: + Mutex semaphores MUST implement recursive locking + Mutex semaphores should implement priority inheritance and deletion safe +*/ + +#endif /* osiSemh */ diff --git a/src/libCom/osi/osiThread.h b/src/libCom/osi/osiThread.h new file mode 100644 index 000000000..394e3887b --- /dev/null +++ b/src/libCom/osi/osiThread.h @@ -0,0 +1,68 @@ +#ifndef osiThreadh +#define osiThreadh + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shareLib.h" + +typedef void (*THREADFUNC)(void *parm); + +#define threadPriorityMax 99 +#define threadPriorityMin 0 + +/*some generic values */ +#define threadPriorityLow 10 +#define threadPriorityMedium 50 +#define threadPriorityHigh 90 + + +/*some iocCore specific values */ +#define threadPriorityChannelAccessClient 10 +#define threadPriorityChannelAccessServer 20 +#define threadPriorityScanLow 60 +#define threadPriorityScanHigh 70 + +/* + *The following functions convert to/from osi (operating system independent) + * and oss (operating system specific) priority values + * NOTE THAT ALL OTHER CALLS USE osi priority values +*/ + +epicsShareFunc int epicsShareAPI threadGetOsiPriorityValue(int ossPriority); +epicsShareFunc int epicsShareAPI threadGetOssPriorityValue(int osiPriority); + +/* stack sizes for each stackSizeClass are implementation and CPU dependent */ +typedef enum { + threadStackSmall, threadStackMedium, threadStackBig +} threadStackSizeClass; + +epicsShareFunc unsigned int epicsShareAPI threadGetStackSize(threadStackSizeClass size); + +typedef void *threadId; +epicsShareFunc threadId epicsShareAPI threadCreate(const char *name, + unsigned int priority, unsigned int stackSize, + THREADFUNC funptr,void *parm); +epicsShareFunc void epicsShareAPI threadDestroy(threadId id); +epicsShareFunc void epicsShareAPI threadSuspend(threadId id); +epicsShareFunc void epicsShareAPI threadResume(threadId id); +epicsShareFunc int epicsShareAPI threadGetPriority(threadId id); +epicsShareFunc void epicsShareAPI threadSetPriority(threadId id,int priority); +epicsShareFunc void epicsShareAPI threadSetDestroySafe(threadId id); +epicsShareFunc void epicsShareAPI threadSetDestroyUnsafe(threadId id); +epicsShareFunc const char * epicsShareAPI threadGetName(threadId id); +epicsShareFunc int epicsShareAPI threadIsEqual(threadId id1, threadId id2); +epicsShareFunc int epicsShareAPI threadIsReady(threadId id); +epicsShareFunc int epicsShareAPI threadIsSuspended(threadId id); +epicsShareFunc void epicsShareAPI threadSleep(double seconds); +epicsShareFunc threadId epicsShareAPI threadGetIdSelf(void); +epicsShareFunc void epicsShareAPI threadLockContextSwitch(void); +epicsShareFunc void epicsShareAPI threadUnlockContextSwitch(void); +epicsShareFunc threadId epicsShareAPI threadNameToId(const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* osiThreadh */ diff --git a/src/libCom/osi/osiTime.cpp b/src/libCom/osi/osiTime.cpp new file mode 100644 index 000000000..aba5b38e4 --- /dev/null +++ b/src/libCom/osi/osiTime.cpp @@ -0,0 +1,570 @@ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + */ + +#include +#include + +#define epicsExportSharedSymbols +#include "epicsAssert.h" +#include "tsDefs.h" +#include "envDefs.h" +#include "osiTime.h" + +// +// useful public constants +// +const unsigned osiTime::mSecPerSec = 1000u; +const unsigned osiTime::uSecPerSec = 1000u*osiTime::mSecPerSec; +const unsigned osiTime::nSecPerSec = 1000u*osiTime::uSecPerSec; +const unsigned osiTime::nSecPerUSec = 1000u; +const unsigned osiTime::secPerMin = 60u; + +// +// this is defined by POSIX 1003.1b (POSIX real time) compilant OS +// +#ifndef CLOCK_REALTIME + + // + // this is part of the POSIX RT standard but some OS + // still do not define this in time.h + // + struct timespec { + time_t tv_sec; /* seconds since some epoch */ + long tv_nsec; /* nanoseconds within the second */ + }; + + struct tm *gmtime_r (const time_t *, struct tm *); + struct tm *localtime_r (const time_t *, struct tm *); +#endif + +// +// force this module to include code that can convert +// to GDD's aitTimeStamp, but dont require that it must +// link with gdd. Therefore, gdd.h is not included here. +// +class aitTimeStamp { +public: + unsigned long tv_sec; + unsigned long tv_nsec; +}; + +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 + +// +// osiTime (const unsigned long secIn, const unsigned long nSecIn) +// +osiTime::osiTime (const unsigned long secIn, const unsigned long nSecIn) +{ + if (nSecInsec = 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; + } +} + +// +// getCurrent () +// +// force a logical progression of time +// +// (this does not appear to add any significant +// overhead when the code is optimized) +// +osiTime osiTime::getCurrent () +{ + static osiTime last; + osiTime ts = osiTime::osdGetCurrent(); + + if (last (difftime (error, current)); + } + + { + time_t first = static_cast (0); + time_t last = static_cast (1); + this->time_tTicksPerSec = 1.0 / difftime (last, first); + } + + { + struct tm tmEpicsEpoch; + time_t epicsEpoch; + time_t ansiEpoch = 0; + + tmEpicsEpoch.tm_sec = 0; + tmEpicsEpoch.tm_min = 0; + tmEpicsEpoch.tm_hour = 0; + tmEpicsEpoch.tm_mday = epicsEpocDayOfTheMonth; + tmEpicsEpoch.tm_mon = epicsEpocMonth; + tmEpicsEpoch.tm_year = epicsEpochYear-tmStructEpochYear; + 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 (difftime (epicsEpoch, ansiEpoch)); + this->epicsEpochOffset -= secWest; + } +} + +// +// ansiSecToInternalSec () +// +unsigned long osiTime::time_tToInternalSec (const time_t &ansiTimeTicks) +{ + unsigned long sec; + + sec = static_cast (ansiTimeTicks / lti.time_tTicksPerSec); + + // expect over / under flow + if (lti.epicsEpochOffset>=0) { + sec -= static_cast(lti.epicsEpochOffset); + } + else { + sec += static_cast(-lti.epicsEpochOffset); + } + + return sec; +} + +// +// operator time_t_wrapper () +// +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(lti.epicsEpochOffset); + } + else { + newSec = this->sec + static_cast(-lti.epicsEpochOffset); + } + tmp = newSec * lti.time_tTicksPerSec; + tmp += (this->nSec * lti.time_tTicksPerSec) / nSecPerSec; + wrap.ts = static_cast (tmp); + return wrap; +} + +// +// convert to and from ANSI C struct tm (with nano seconds) +// +osiTime::operator tm_nano_sec () const +{ + struct tm_nano_sec tm; + time_t_wrapper ansiTimeTicks; + + ansiTimeTicks = *this; + + // from POSIX RT + localtime_r (&ansiTimeTicks.ts, &tm.ansi_tm); + + tm.nsec = this->nSec; + + return tm; +} + +// +// osiTime (const struct tm_nano_sec &tm) +// +osiTime::osiTime (const struct tm_nano_sec &tm) +{ + time_t ansiTimeTicks; + struct tm tmp = tm.ansi_tm; + + ansiTimeTicks = mktime (&tmp); + assert (ansiTimeTicks!=(time_t)-1); + + this->sec = osiTime::time_tToInternalSec (ansiTimeTicks); + this->nSec = tm.nsec; +} + +// +// operator struct timespec () +// +osiTime::operator struct timespec () const +{ + struct timespec ts; + time_t_wrapper ansiTimeTicks; + + ansiTimeTicks = *this; + ts.tv_sec = ansiTimeTicks.ts; + ts.tv_nsec = static_cast (this->nSec); + return ts; +} + +// +// osiTime (const struct timespec &ts) +// +osiTime::osiTime (const struct timespec &ts) +{ + this->sec = osiTime::time_tToInternalSec (ts.tv_sec); + assert (ts.tv_nsec>=0); + unsigned long nSecIn = static_cast (ts.tv_nsec); + if (nSecInnSec = nSecIn; + } + else { + this->sec += nSecIn / nSecPerSec; + this->nSec = nSecIn % nSecPerSec; + } +} + +// +// operator aitTimeStamp () +// +osiTime::operator aitTimeStamp () const +{ + aitTimeStamp ts; + time_t_wrapper ansiTimeTicks; + + ansiTimeTicks = *this; + ts.tv_sec = ansiTimeTicks.ts; + ts.tv_nsec = this->nSec; + return ts; +} + +// +// osiTime (const aitTimeStamp &ts) +// +osiTime::osiTime (const aitTimeStamp &ts) +{ + this->sec = osiTime::time_tToInternalSec (ts.tv_sec); + + if (ts.tv_nsecnSec = ts.tv_nsec; + } + else { + this->sec += ts.tv_nsec / nSecPerSec; + this->nSec = ts.tv_nsec % nSecPerSec; + } +} + +// +// operator TS_STAMP () +// +osiTime::operator struct TS_STAMP () const +{ + struct TS_STAMP ts; + ts.secPastEpoch = this->sec; + ts.nsec = this->nSec; + return ts; +} + +// +// osiTime (const TS_STAMP &ts) +// +osiTime::osiTime (const struct TS_STAMP &ts) +{ + this->sec = ts.secPastEpoch; + this->nSec = ts.nsec; +} + +// +// osiTime::show (unsigned) +// +void osiTime::show (unsigned) const +{ + int status; + char bigBuffer[256]; + tm_nano_sec tmns = *this; + + 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 (tmns.nsec) / nSecPerSec); + } +} + +// +// osiTime::operator + (const long double &rhs) +// +// rhs has units seconds +// +osiTime osiTime::operator + (const long double &rhs) const +{ + unsigned long newSec, newNSec, secOffset, nSecOffset; + long double fnsec; + + if (rhs >= 0) { + secOffset = static_cast (rhs); + fnsec = rhs - static_cast (secOffset); + nSecOffset = static_cast (fnsec * nSecPerSec); + + newSec = this->sec + secOffset; // overflow expected + newNSec = this->nSec + nSecOffset; + if (newNSec >= nSecPerSec) { + newSec++; // overflow expected + newNSec -= nSecPerSec; + } + } + else { + secOffset = static_cast (-rhs); + fnsec = rhs + static_cast (secOffset); + nSecOffset = static_cast (-fnsec * nSecPerSec); + + newSec = this->sec - secOffset; // underflow expected + if (this->nSec>=nSecOffset) { + newNSec = this->nSec - nSecOffset; + } + else { + // borrow + newSec--; // underflow expected + newNSec = this->nSec + (nSecPerSec - nSecOffset); + } + } + return osiTime (newSec, newNSec); +} + +// +// operator - +// +// To make this code robust during timestamp rollover events +// time stamp differences greater than one half full scale are +// interpreted as rollover situations: +// +// when RHS is greater than THIS: +// RHS-THIS > one half full scale => return THIS + (ULONG_MAX-RHS) +// RHS-THIS <= one half full scale => return -(RHS-THIS) +// +// when THIS is greater than or equal to RHS +// THIS-RHS > one half full scale => return -(RHS + (ULONG_MAX-THIS)) +// THIS-RHS <= one half full scale => return THIS-RHS +// +long double osiTime::operator - (const osiTime &rhs) const +{ + long double nSecRes, secRes; + + // + // first compute the difference between the nano-seconds members + // + // nano sec member is not allowed to be greater that 1/2 full scale + // so the unsigned to signed conversion is ok + // + if (this->nSec>=rhs.nSec) { + nSecRes = this->nSec - rhs.nSec; + } + else { + nSecRes = rhs.nSec - this->nSec; + nSecRes = -nSecRes; + } + + // + // next compute the difference between the seconds memebers + // and invert the sign of the nano seconds result if there + // is a range violation + // + if (this->secsec; + if (secRes > ULONG_MAX/2) { + // + // In this situation where the difference is more than + // 68 years assume that the seconds counter has rolled + // over and compute the "wrap around" difference + // + secRes = 1 + (ULONG_MAX-secRes); + nSecRes = -nSecRes; + } + else { + secRes = -secRes; + } + } + else { + secRes = this->sec - rhs.sec; + if (secRes > ULONG_MAX/2) { + // + // In this situation where the difference is more than + // 68 years assume that the seconds counter has rolled + // over and compute the "wrap around" difference + // + secRes = 1 + (ULONG_MAX-secRes); + secRes = -secRes; + nSecRes = -nSecRes; + } + } + + return secRes + nSecRes/nSecPerSec; +} + +// +// operator <= +// +bool osiTime::operator <= (const osiTime &rhs) const +{ + bool rc; + + if (this->secsec < ULONG_MAX/2) { + // + // In this situation where the difference is less than + // 69 years compute the expected result + // + rc = true; + } + else { + // + // In this situation where the difference is more than + // 69 years assume that the seconds counter has rolled + // over and compute the "wrap around" result + // + rc = false; + } + } + else if (this->sec>rhs.sec) { + if (this->sec-rhs.sec < ULONG_MAX/2) { + // + // In this situation where the difference is less than + // 69 years compute the expected result + // + rc = false; + } + else { + // + // In this situation where the difference is more than + // 69 years assume that the seconds counter has rolled + // over and compute the "wrap around" result + // + rc = true; + } + } + else { + if (this->nSec<=rhs.nSec) { + rc = true; + } + else { + rc = false; + } + } + return rc; +} + +// +// operator < +// +bool osiTime::operator < (const osiTime &rhs) const +{ + bool rc; + + if (this->secsec < ULONG_MAX/2) { + // + // In this situation where the difference is less than + // 69 years compute the expected result + // + rc = true; + } + else { + // + // In this situation where the difference is more than + // 69 years assume that the seconds counter has rolled + // over and compute the "wrap around" result + // + rc = false; + } + } + else if (this->sec>rhs.sec) { + if (this->sec-rhs.sec < ULONG_MAX/2) { + // + // In this situation where the difference is less than + // 69 years compute the expected result + // + rc = false; + } + else { + // + // In this situation where the difference is more than + // 69 years assume that the seconds counter has rolled + // over and compute the "wrap around" result + // + rc = true; + } + } + else { + if (this->nSec + +#include "shareLib.h" + +struct TS_STAMP; // EPICS +class aitTimeStamp; // GDD +struct timespec; // POSIX real time + +// +// 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 +}; + +// +// 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 osiTime +// +// high resolution osiTime stamp +// +class epicsShareClass osiTime { +public: + + // + // 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 + // + static void synchronize(); + + // + // create an osiTime for the EPICS epoch + // + osiTime (); + osiTime (const osiTime &t); + + // + // 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 + // + 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 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 + // + operator aitTimeStamp () const; + osiTime (const aitTimeStamp &ts); + osiTime operator = (const aitTimeStamp &rhs); + + // + // 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 + // + bool operator == (const osiTime &rhs) const; + bool operator != (const osiTime &rhs) const; + bool operator <= (const osiTime &rhs) const; + bool operator < (const osiTime &rhs) const; + bool operator >= (const osiTime &rhs) const; + bool operator > (const osiTime &rhs) const; + + // + // dump current state to standard out + // + void show (unsigned interestLevel) const; + + // + // useful public constants + // + static const unsigned secPerMin; + static const unsigned mSecPerSec; + static const unsigned uSecPerSec; + static const unsigned nSecPerSec; + 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) + // + osiTime (const unsigned long sec, const unsigned long nSec); +}; + +///////////////////////////////////// +// +// time inline member functions +// +///////////////////////////////////// + +inline osiTime::osiTime () : sec(0u), nSec(0u) {} + +inline osiTime::osiTime (const osiTime &t) : sec(t.sec), nSec(t.nSec) {} + +inline osiTime osiTime::operator - (const long double &rhs) const +{ + return osiTime::operator + (-rhs); +} + +inline osiTime osiTime::operator += (const long double &rhs) +{ + *this = osiTime::operator + (rhs); + return *this; +} + +inline osiTime osiTime::operator -= (const long double &rhs) +{ + *this = osiTime::operator + (-rhs); + return *this; +} + +inline bool osiTime::operator == (const osiTime &rhs) const +{ + if (this->sec == rhs.sec && this->nSec == rhs.nSec) { + return true; + } + else { + return false; + } +} + +// +// 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) +{ + 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) +{ + this->sec = osiTime::time_tToInternalSec (ansiTimeTicks.ts); + this->nSec = 0; +} + +// +// 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 +