added non-threaded timer queue and epicsTimer C interface

This commit is contained in:
Jeff Hill
2001-02-20 23:41:03 +00:00
parent 1867f33eeb
commit 7b3c96471d
6 changed files with 332 additions and 101 deletions

View File

@@ -28,97 +28,175 @@
*
*/
#include <typeinfo>
#define epicsExportSharedSymbols
#include "epicsTimer.h"
#if 0
#include "tsFreeList.h"
#include "tsDLList.h"
#include "epicsMutex.h"
#include "locationException.h"
#include "errlog.h"
#endif
#include "epicsTimerPrivate.h"
epicsTimerQueueNonThreaded::~epicsTimerQueueNonThreaded () {}
void epicsTimerNotify::show ( unsigned /* level */ ) const {}
#if 0
class epicsTimerForC : public epicsTimer {
epicsShareFunc virtual void expire ();
epicsShareFunc virtual void destroy ();
epicsShareFunc virtual bool again () const;
epicsShareFunc virtual double delay () const;
epicsShareFunc virtual void show ( unsigned level ) const;
const epicsTimerJumpTable &jt;
void * pPrivate;
class epicsTimerNotifyForC : public epicsTimerNotify {
public:
epicsTimerForC ( const epicsTimerJumpTable &jtIn, epicsTimerQueue &queue, void *pPrivateIn );
epicsTimerNotifyForC ( epicsTimerCallback, void *pPrivateIn );
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
virtual ~epicsTimerNotifyForC ();
private:
epicsTimerCallback pCallBack;
void * pPrivate;
expireStatus expire ();
static tsFreeList < epicsTimerNotifyForC > freeList;
};
epicsTimerForC::epicsTimerForC ( const epicsTimerJumpTable &jtIn, epicsTimerQueue &queue, void *pPrivateIn ) :
epicsTimer ( queue ), jt ( jtIn ), pPrivate ( pPrivateIn ) {}
tsFreeList < epicsTimerNotifyForC > epicsTimerNotifyForC::freeList;
void epicsTimerForC::expire ()
{
( *this->jt.expire ) ( this->pPrivate );
inline void * epicsTimerNotifyForC::operator new ( size_t size )
{
return epicsTimerNotifyForC::freeList.allocate ( size );
}
void epicsTimerForC::destroy ()
{
( *this->jt.destroy ) ( this->pPrivate );
inline void epicsTimerNotifyForC::operator delete ( void *pCadaver, size_t size )
{
epicsTimerNotifyForC::freeList.release ( pCadaver, size );
}
bool epicsTimerForC::again () const
epicsTimerNotifyForC::epicsTimerNotifyForC ( epicsTimerCallback pCBIn, void *pPrivateIn ) :
pCallBack ( pCBIn ), pPrivate ( pPrivateIn ) {}
epicsTimerNotifyForC::~epicsTimerNotifyForC () {}
epicsTimerNotify::expireStatus epicsTimerNotifyForC::expire ()
{
return ( *this->jt.again ) ( this->pPrivate ) ? true : false ;
( *this->pCallBack ) ( this->pPrivate );
return noRestart;
}
double epicsTimerForC::delay () const
extern "C" epicsNonThreadedTimerQueueId epicsShareAPI
epicsNonThreadedTimerQueueAllocate ()
{
return ( *this->jt.delay ) ( this->pPrivate );
try {
epicsNonThreadedTimerQueue &queue =
epicsNonThreadedTimerQueue::allocate ();
return &queue;
}
catch ( ... ) {
return 0;
}
}
void epicsTimerForC::show ( unsigned level ) const
extern "C" void epicsShareAPI
epicsNonThreadedTimerQueueRelease ( epicsNonThreadedTimerQueueId pQueue )
{
( *this->jt.show ) ( this->pPrivate, level );
pQueue->release ();
}
extern "C" epicsShareFunc epicsTimerId epicsShareAPI epicsTimerCreate (
const epicsTimerJumpTable *pjtIn, epicsTimerQueueId queueIdIn, void *pPrivateIn )
extern "C" void epicsShareAPI
epicsNonThreadedTimerQueueProcess ( epicsNonThreadedTimerQueueId pQueue )
{
assert ( pjtIn );
assert ( queueIdIn );
return ( epicsTimerId ) new epicsTimerForC
( *pjtIn, *static_cast < epicsTimerQueue * > ( queueIdIn ), pPrivateIn );
pQueue->process ();
}
extern "C" epicsShareFunc void epicsShareAPI epicsTimerArm ( epicsTimerId tmrIdIn, double delay )
extern "C" double epicsShareAPI
epicsNonThreadedTimerQueueGetDelayToNextExpire (
epicsNonThreadedTimerQueueId pQueue )
{
epicsTimerForC *pTmr = static_cast < epicsTimerForC * > ( tmrIdIn );
assert ( pTmr );
pTmr->reschedule ( delay );
return pQueue->getNextExpireDelay ();
}
extern "C" epicsShareFunc void epicsShareAPI epicsTimerCancel ( epicsTimerId tmrIdIn )
extern "C" epicsTimerId epicsShareAPI epicsNonThreadedTimerQueueCreateTimer (
epicsNonThreadedTimerQueueId pQueue,
epicsTimerCallback pCallback, void *pArg )
{
try {
epicsTimerNotifyForC *pNotify = new epicsTimerNotifyForC ( pCallback, pArg );
if ( ! pNotify ) {
throw timer::noMemory ();
}
epicsTimer &tmr = pQueue->createTimer ( *pNotify );
return &tmr;
}
catch ( ... ) {
return 0;
}
}
extern "C" void epicsShareAPI epicsNonThreadedTimerQueueShow (
epicsNonThreadedTimerQueueId pQueue, unsigned int level )
{
pQueue->show ( level );
}
extern "C" epicsThreadedTimerQueueId epicsShareAPI
epicsThreadedTimerQueueCreate ( int okToShare, unsigned int threadPriority )
{
try {
epicsThreadedTimerQueue & queue =
epicsThreadedTimerQueue::allocate
( okToShare ? true : false, threadPriority );
return &queue;
}
catch ( ... ) {
return 0;
}
}
extern "C" void epicsShareAPI epicsThreadedTimerQueueDelete ( epicsThreadedTimerQueueId pQueue )
{
pQueue->release ();
}
extern "C" epicsTimerId epicsShareAPI epicsThreadedTimerQueueCreateTimer (
epicsThreadedTimerQueueId pQueue, epicsTimerCallback pCallback, void *pArg )
{
try {
epicsTimerNotifyForC *pNotify = new epicsTimerNotifyForC ( pCallback, pArg );
if ( ! pNotify ) {
throw timer::noMemory ();
}
epicsTimer &tmr = pQueue->createTimer ( *pNotify );
return &tmr;
}
catch ( ... ) {
return 0;
}
}
extern "C" void epicsShareAPI epicsThreadedTimerQueueShow (
epicsThreadedTimerQueueId pQueue, unsigned int level )
{
pQueue->show ( level );
}
extern "C" void epicsShareAPI epicsTimerDestroy ( epicsTimerId pTmr )
{
delete pTmr;
}
extern "C" void epicsShareAPI epicsTimerStartTime (
epicsTimerId pTmr, const epicsTimeStamp *pTime )
{
pTmr->start ( *pTime );
}
extern "C" void epicsShareAPI epicsTimerStartDelay (
epicsTimerId pTmr, double delaySeconds )
{
pTmr->start ( delaySeconds );
}
extern "C" void epicsShareAPI epicsTimerCancel ( epicsTimerId pTmr )
{
epicsTimerForC *pTmr = static_cast < epicsTimerForC * > ( tmrIdIn );
assert ( pTmr );
pTmr->cancel ();
}
extern "C" epicsShareFunc double epicsShareAPI epicsTimerTimeRemaining ( epicsTimerId idIn )
extern "C" double epicsShareAPI epicsTimerGetExpireDelay ( epicsTimerId pTmr )
{
epicsTimerForC *pTmr = static_cast < epicsTimerForC * > ( idIn );
assert ( pTmr );
return pTmr->timeRemaining ();
return pTmr->getExpireDelay ();
}
extern "C" epicsShareFunc epicsTimeStamp epicsShareAPI epicsTimerExpirationDate ( epicsTimerId idIn )
extern "C" void epicsShareAPI epicsTimerShow (
epicsTimerId pTmr, unsigned int level )
{
epicsTimerForC *pTmr = static_cast < epicsTimerForC * > ( idIn );
assert ( pTmr );
return pTmr->expirationDate ();
pTmr->show ( level );
}
#endif

View File

@@ -39,7 +39,7 @@ public:
virtual void show ( unsigned int level ) const;
};
class epicsShareClass epicsTimer {
struct epicsShareClass epicsTimer {
public:
virtual ~epicsTimer () = 0;
virtual void start ( const epicsTime & ) = 0;
@@ -49,27 +49,27 @@ public:
virtual void show ( unsigned int level ) const = 0;
};
class epicsShareClass epicsTimerQueueThreaded {
struct epicsShareClass epicsThreadedTimerQueue {
public:
static epicsTimerQueueThreaded & create (
static epicsThreadedTimerQueue & allocate (
bool okToShare, int threadPriority = epicsThreadPriorityMin + 10 );
virtual void release () = 0;
virtual epicsTimer & createTimer ( epicsTimerNotify & ) = 0;
virtual void show ( unsigned int level ) const = 0;
virtual void release () = 0;
protected:
virtual ~epicsTimerQueueThreaded () = 0;
virtual ~epicsThreadedTimerQueue () = 0;
};
class epicsShareClass epicsTimerQueueNonThreaded {
struct epicsShareClass epicsNonThreadedTimerQueue {
public:
static epicsTimerQueueNonThreaded & create ();
static epicsNonThreadedTimerQueue & allocate ();
virtual void release () = 0;
virtual epicsTimer & createTimer ( epicsTimerNotify & ) = 0;
virtual void process () = 0;
virtual double getNextExpireDelay () const = 0;
virtual void show ( unsigned int level ) const = 0;
virtual void release () = 0;
protected:
virtual ~epicsTimerQueueNonThreaded () = 0;
virtual ~epicsNonThreadedTimerQueue () = 0;
};
inline epicsTimerNotify::expireStatus::expireStatus ( restart_t restart ) :
@@ -96,41 +96,50 @@ inline double epicsTimerNotify::expireStatus::expirationDelay () const
return this->delay;
}
extern "C" {
#endif /* __cplusplus */
typedef void *epicsTimerQueueId;
epicsShareFunc epicsTimerQueueId* epicsShareAPI
epicsTimerQueueCreateNonThreaded ();
epicsShareFunc epicsTimerQueueId* epicsShareAPI
epicsTimerQueueCreateThreaded ( unsigned int threadPriority, int okToShare );
epicsShareFunc void epicsShareAPI epicsTimerQueueDelete ( epicsTimerQueueId );
epicsShareFunc void epicsShareAPI epicsTimerQueueProcess ( epicsTimerQueueId );
epicsShareFunc int epicsShareAPI epicsTimerQueueGetExpireTime (
epicsTimerQueueId, epicsTimeStamp *time );
epicsShareFunc void epicsShareAPI epicsTimerQueueShow (
epicsTimerQueueId id, unsigned int level );
typedef void *epicsTimerId;
typedef struct epicsNonThreadedTimerQueue * epicsNonThreadedTimerQueueId;
typedef struct epicsThreadedTimerQueue * epicsThreadedTimerQueueId;
typedef struct epicsTimer * epicsTimerId;
typedef void ( *epicsTimerCallback ) ( void * );
epicsShareFunc epicsTimerId epicsShareAPI epicsTimerCreate (
epicsTimerQueueId queueid,epicsTimerCallback callback, void *arg );
epicsShareFunc void epicsShareAPI epicsTimerDestroy ( epicsTimerId id );
epicsShareFunc epicsNonThreadedTimerQueueId epicsShareAPI
epicsNonThreadedTimerQueueAttach ();
epicsShareFunc void epicsShareAPI
epicsNonThreadedTimerQueueRelease ( epicsNonThreadedTimerQueueId );
epicsShareFunc void epicsShareAPI
epicsNonThreadedTimerQueueProcess ( epicsNonThreadedTimerQueueId );
epicsShareFunc double epicsShareAPI
epicsNonThreadedTimerQueueGetDelayToNextExpire (
epicsNonThreadedTimerQueueId );
epicsShareFunc epicsTimerId epicsShareAPI epicsNonThreadedTimerQueueCreateTimer (
epicsNonThreadedTimerQueueId queueid, epicsTimerCallback pCallback, void *pArg );
epicsShareFunc void epicsShareAPI epicsNonThreadedTimerQueueShow (
epicsNonThreadedTimerQueueId id, unsigned int level );
epicsShareFunc void epicsShareAPI epicsTimerStartTime (
epicsTimerId id,epicsTimeStamp *time );
epicsShareFunc void epicsShareAPI epicsTimerStartDelay (
epicsTimerId id,double delaySeconds );
epicsShareFunc void epicsShareAPI epicsTimerCancel ( epicsTimerId id );
/* GetExpireTime returns (0,1) if time (is not, is) given a value */
epicsShareFunc int epicsShareAPI epicsTimerGetExpireTime (
epicsTimerId id, epicsTimeStamp *time);
epicsShareFunc void epicsShareAPI epicsTimerShow (
epicsTimerId id, unsigned int level );
epicsShareFunc epicsThreadedTimerQueueId epicsShareAPI
epicsThreadedTimerQueueAttach ( int okToShare, unsigned int threadPriority );
epicsShareFunc void epicsShareAPI
epicsThreadedTimerQueueRelease ( epicsThreadedTimerQueueId );
epicsShareFunc epicsTimerId epicsShareAPI
epicsThreadedTimerQueueCreateTimer ( epicsThreadedTimerQueueId queueid,
epicsTimerCallback callback, void *arg );
epicsShareFunc void epicsShareAPI
epicsThreadedTimerQueueShow ( epicsThreadedTimerQueueId id, unsigned int level );
epicsShareFunc void epicsShareAPI
epicsTimerDestroy ( epicsTimerId id );
epicsShareFunc void epicsShareAPI
epicsTimerStartTime ( epicsTimerId id, const epicsTimeStamp *pTime );
epicsShareFunc void epicsShareAPI
epicsTimerStartDelay ( epicsTimerId id, double delaySeconds );
epicsShareFunc void epicsShareAPI
epicsTimerCancel ( epicsTimerId id );
epicsShareFunc double epicsShareAPI
epicsTimerGetExpireDelay ( epicsTimerId id );
epicsShareFunc void epicsShareAPI
epicsTimerShow ( epicsTimerId id, unsigned int level );
#ifdef __cplusplus
}

View File

@@ -100,7 +100,7 @@ private:
friend class timerQueueThreadedMgr;
};
class timerQueueThreaded : public epicsTimerQueueThreaded,
class timerQueueThreaded : public epicsThreadedTimerQueue,
public epicsThreadRunable, public timerQueueNotify,
public timerQueueThreadedMgrPrivate,
public tsDLNode < timerQueueThreaded > {
@@ -131,7 +131,7 @@ private:
class timerQueueThreadedMgr {
public:
~timerQueueThreadedMgr ();
timerQueueThreaded & create ( bool okToShare,
timerQueueThreaded & allocate ( bool okToShare,
int threadPriority = epicsThreadPriorityMin + 10 );
void release ( timerQueueThreaded & );
private:
@@ -139,6 +139,25 @@ private:
tsDLList < timerQueueThreaded > sharedQueueList;
};
class timerQueueNonThreaded : public epicsNonThreadedTimerQueue,
public timerQueueNotify {
public:
timerQueueNonThreaded ();
~timerQueueNonThreaded ();
epicsTimer & createTimer ( epicsTimerNotify & );
void process ();
double getNextExpireDelay () const;
void reschedule ();
void show ( unsigned int level ) const;
void release ();
static timerQueueNonThreaded & allocate ();
private:
timerQueue queue;
static epicsMutex mutex;
static timerQueueNonThreaded *pQueue;
static unsigned useCount;
};
inline void * timer::operator new ( size_t size )
{
return timer::freeList.allocate ( size );

View File

@@ -0,0 +1,125 @@
/*
* $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
*
*/
#define epicsExportSharedSymbols
#include "epicsTimerPrivate.h"
unsigned timerQueueNonThreaded::useCount;
timerQueueNonThreaded * timerQueueNonThreaded::pQueue;
epicsMutex timerQueueNonThreaded::mutex;
epicsNonThreadedTimerQueue::~epicsNonThreadedTimerQueue () {}
epicsNonThreadedTimerQueue &epicsNonThreadedTimerQueue::allocate ()
{
return epicsNonThreadedTimerQueue::allocate ();
}
timerQueueNonThreaded &timerQueueNonThreaded::allocate ()
{
epicsAutoMutex locker ( timerQueueNonThreaded::mutex );
if ( timerQueueNonThreaded::pQueue ) {
timerQueueNonThreaded::useCount++;
return *timerQueueNonThreaded::pQueue;
}
else {
timerQueueNonThreaded::pQueue = new timerQueueNonThreaded ();
if ( ! timerQueueNonThreaded::pQueue ) {
throw timer::noMemory ();
}
timerQueueNonThreaded::useCount = 1u;
return *timerQueueNonThreaded::pQueue;
}
}
timerQueueNonThreaded::timerQueueNonThreaded () :
queue ( *this )
{
}
timerQueueNonThreaded::~timerQueueNonThreaded ()
{
}
void timerQueueNonThreaded::release ()
{
epicsAutoMutex locker ( timerQueueNonThreaded::mutex );
assert ( timerQueueNonThreaded::useCount >= 1u );
timerQueueNonThreaded::useCount--;
if ( timerQueueNonThreaded::useCount == 0u ) {
delete timerQueueNonThreaded::pQueue;
timerQueueNonThreaded::pQueue = 0;
}
}
epicsTimer & timerQueueNonThreaded::createTimer ( epicsTimerNotify & notify )
{
timer *pTmr = new timer ( notify, this->queue );
if ( ! pTmr ) {
throwWithLocation ( timer::noMemory () );
}
return *pTmr;
}
void timerQueueNonThreaded::reschedule ()
{
//
// Only useful in a multi-threaded program ...
//
// If a select() based file descriptor manager was waiting
// in select () this routine should force it to wake up
// and rescheduale its delay, but since file descriptor managers
// typically are only be used in single-threaded programs, and
// in fact the file descriptor manager currently supplied
// with EPICS is not thread safe, then perhaps
// its not worth the effort to tightly integrate this with
// the file descriptor manager so that this can be implemented.
//
}
void timerQueueNonThreaded::process ()
{
this->queue.process ();
}
double timerQueueNonThreaded::getNextExpireDelay () const
{
return this->queue.delayToFirstExpire ();
}
void timerQueueNonThreaded::show ( unsigned int level ) const
{
printf ( "EPICS non-threaded timer queue at %p\n",
static_cast <const void *> ( this ) );
if ( level >=1u ) {
this->queue.show ( level - 1u );
}
}

View File

@@ -33,11 +33,11 @@
static timerQueueThreadedMgr queueMgr;
epicsTimerQueueThreaded::~epicsTimerQueueThreaded () {}
epicsThreadedTimerQueue::~epicsThreadedTimerQueue () {}
epicsTimerQueueThreaded &epicsTimerQueueThreaded::create ( bool okToShare, int threadPriority )
epicsThreadedTimerQueue &epicsThreadedTimerQueue::allocate ( bool okToShare, int threadPriority )
{
return queueMgr.create ( okToShare, threadPriority );
return queueMgr.allocate ( okToShare, threadPriority );
}
tsFreeList < class timerQueueThreaded, 0x8 > timerQueueThreaded::freeList;
@@ -45,7 +45,7 @@ tsFreeList < class timerQueueThreaded, 0x8 > timerQueueThreaded::freeList;
timerQueueThreaded::timerQueueThreaded ( bool okToShareIn, unsigned priority ) :
queue ( *this ), thread ( *this, "epicsTimerQueue",
epicsThreadGetStackSize ( epicsThreadStackMedium ), priority ),
okToShare (okToShareIn), exitFlag ( false ), terminateFlag ( false )
okToShare ( okToShareIn ), exitFlag ( false ), terminateFlag ( false )
{
this->thread.start ();
}

View File

@@ -38,7 +38,7 @@ timerQueueThreadedMgr::~timerQueueThreadedMgr ()
epicsAutoMutex locker ( this->mutex );
}
timerQueueThreaded & timerQueueThreadedMgr::create (
timerQueueThreaded & timerQueueThreadedMgr::allocate (
bool okToShare, int threadPriority )
{
epicsAutoMutex locker ( this->mutex );