254 lines
7.3 KiB
C++
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 */
|
|
|