Files
epics-base/src/libCom/timer/osiTimer.h
2001-01-31 13:34:02 +00:00

254 lines
7.3 KiB
C++

/*
* $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
*
*/
#ifndef osiTimerHInclude
#define osiTimerHInclude
#include "shareLib.h" /* reset share lib defines */
#include "epicsThread.h"
#include "epicsTime.h"
#ifdef __cplusplus
#include "epicsTime.h"
#include "tsDLList.h"
#include "epicsMutex.h"
#include "epicsEvent.h"
class osiTimerQueue;
/*
* osiTimer
*/
class osiTimer : public tsDLNode <osiTimer> {
public:
class noDelaySpecified {}; /* exception */
class noMemory {}; /* exception */
/*
* Create an active timer that will expire delay seconds after it is created
* or create an inactive timer respectively.
*
* ** Warning ** default timer queue has no manager thread and is typically
* processed by the file descriptor manager
*/
epicsShareFunc osiTimer ( double delay, osiTimerQueue & queueIn );
epicsShareFunc osiTimer ( double delay );
/*
* Create an inactive timer
*
* ** Warning ** default timer queue has no manager thread and is typically
* processed by the file descriptor manager
*/
epicsShareFunc osiTimer ( osiTimerQueue & queueIn );
epicsShareFunc osiTimer ();
/*
* change the timers expiration to newDelay
* seconds after when reschedule() is called
*/
epicsShareFunc void reschedule (double newDelay);
/*
* change the timers expiration to this->delay()
* seconds after when reschedule() is called
*/
epicsShareFunc void reschedule ();
/*
* Start the timer with delay newDelay if inactive.
*/
epicsShareFunc void activate ( double newDelay );
/*
* Start the timer with delay this->delay() if inactive.
*/
epicsShareFunc void activate ();
/*
* inactivate the timer and call the virtual destroy()
* member function
*/
epicsShareFunc void cancel ();
/*
* return the number of seconds remaining before
* this osiTimer will expire or the expiration date
* respectively
*/
epicsShareFunc double timeRemaining () const; /* returns seconds, but inefficent */
epicsShareFunc epicsTime expirationDate () const; /* efficent */
/*
* called when the osiTimer expires
*/
epicsShareFunc virtual void expire () = 0;
/*
* called if
* 1) osiTimer exists and the osiTimerQueue is deleted
* 2) when the osiTimer expires and again() returns false
*
* osiTimer::destroy() does a "delete this"
*
* if the derived class replaces this function then it
* is taking responsibility for freeing (deleting)
* timer resources when they are nolonger needed.
*/
epicsShareFunc virtual void destroy ();
/*
* returning true indicates that the
* osiTimer should be rearmed with delay
* "delay()" when it expires
*
* the defaut osiTimer::again() returns false
* (run the osiTimer once only)
*/
epicsShareFunc virtual bool again () const;
/*
* returns the delay prior to expire
* for subsequent iterations (if "again()"
* returns true)
*
* the default osiTimer::delay() throws the
* exception type noDelaySpecified, but it will
* not be called unless the again() virtual
* function returns true.
*/
epicsShareFunc virtual double delay () const;
epicsShareFunc virtual void show (unsigned level) const;
/*
* for diagnostics
*/
epicsShareFunc virtual const char *name () const;
epicsShareFunc virtual ~osiTimer ();
private:
friend class osiTimerQueue;
enum state {statePending, stateExpired, stateIdle,
numberOfTimerLists, stateLimbo};
epicsTime exp; /* experation time */
state curState; /* current state */
osiTimerQueue &queue; /* pointer to current timer queue */
/*
* place osiTimer in the pending queue
*/
void arm (double initialDelay);
};
/*
* osiTimerQueue
*/
class osiTimerQueue {
friend class osiTimer;
friend class osiTimerThread;
public:
enum managerThreadSelect {
mtsNoManagerThread, // you must call the process method (or the fdManager) to expire timers
mtsCreateManagerThread // manager thread expires timers asnychronously
};
epicsShareFunc osiTimerQueue ( managerThreadSelect mts,
unsigned managerThreadPriority = epicsThreadPriorityMin );
epicsShareFunc virtual ~osiTimerQueue();
epicsShareFunc double delayToFirstExpire () const; /* returns seconds */
epicsShareFunc void process ();
epicsShareFunc void show (unsigned level) const;
private:
epicsMutex mutex;
epicsEvent rescheduleEvent;
epicsEvent exitEvent;
tsDLList <osiTimer> timerLists [osiTimer::numberOfTimerLists];
osiTimer *pExpireTmr;
class osiTimerThread *pMgrThread;
unsigned mgrThreadPriority;
bool inProcess;
bool terminateFlag;
bool exitFlag;
void install (osiTimer &tmr, double delay);
void privateProcess ();
void terminateManagerThread ();
};
/*
* ** Warning **
* the default timer queue has no manager thread and is typically
* processed by the file descriptor manager
*/
epicsShareExtern osiTimerQueue osiDefaultTimerQueue;
inline epicsTime osiTimer::expirationDate () const
{
return this->exp;
}
#endif /* ifdef __cplusplus */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* osiTimerJumpTable
*/
typedef struct osiTimerJumpTable {
void (*expire) (void *pPrivate); /* called when timer expires */
void (*destroy) (void *pPrivate); /* called after expire() when again() is false */
int (*again) (void *pPrivate); /* rearm after expire when again() is true */
double (*delay) (void *pPrivate); /* rearm delay */
void (*show) (void *pPrivate, unsigned level); /* diagnostic */
}osiTimerJumpTable;
typedef void * osiTimerQueueId;
/* see epicsThread.h for the range of priorities allowed here */
epicsShareFunc osiTimerQueueId epicsShareAPI osiTimerQueueCreate (unsigned managerThreadPriority);
typedef void * osiTimerId;
epicsShareFunc osiTimerId epicsShareAPI osiTimerCreate (const osiTimerJumpTable *, osiTimerQueueId, void *pPrivate);
epicsShareFunc void epicsShareAPI osiTimerArm (osiTimerId, double delay);
epicsShareFunc void epicsShareAPI osiTimerCancel (osiTimerId);
epicsShareFunc double epicsShareAPI osiTimerTimeRemaining (osiTimerId);
epicsShareFunc epicsTimeStamp epicsShareAPI osiTimerExpirationDate (osiTimerId);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* osiTimerHInclude */