This is Unofficial EPICS BASE Doxygen Site
timerQueueActive.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2015 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*
10  * Author Jeffrey O. Hill
11  * johill@lanl.gov
12  * 505 665 1831
13  */
14 
15 #include <stdio.h>
16 
17 #include "epicsAtomic.h"
18 #include "timerPrivate.h"
19 #include "errlog.h"
20 
21 #ifdef _MSC_VER
22 # pragma warning ( push )
23 # pragma warning ( disable:4660 )
24 #endif
25 
27 
28 #ifdef _MSC_VER
29 # pragma warning ( pop )
30 #endif
31 
33 
34 epicsTimerQueueActive::~epicsTimerQueueActive () {}
35 
36 epicsTimerQueueActive & epicsTimerQueueActive::allocate ( bool okToShare, unsigned threadPriority )
37 {
39  timerQueueMgrEPICS.getReference ();
40  return pMgr->allocate ( pMgr, okToShare, threadPriority );
41 }
42 
45  bool okToShareIn, unsigned priority ) :
46  _refMgr ( refMgr ), queue ( *this ), thread ( *this, "timerQueue",
48  sleepQuantum ( epicsThreadSleepQuantum() ), okToShare ( okToShareIn ),
49  exitFlag ( 0 ), terminateFlag ( false )
50 {
51 }
52 
54 {
55  this->thread.start ();
56 }
57 
59 {
60  this->terminateFlag = true;
61  this->rescheduleEvent.signal ();
62  while ( ! epics::atomic::get(this->exitFlag) ) {
63  this->exitEvent.wait ( 1.0 );
64  }
65  // in case other threads are waiting here also
66  this->exitEvent.signal ();
67 }
68 
69 void timerQueueActive :: _printLastChanceExceptionMessage (
70  const char * pExceptionTypeName,
71  const char * pExceptionContext )
72 {
73  char date[64];
74  try {
75  epicsTime cur = epicsTime :: getCurrent ();
76  cur.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S.%f");
77  }
78  catch ( ... ) {
79  strcpy ( date, "<UKN DATE>" );
80  }
81  errlogPrintf (
82  "timerQueueActive: Unexpected C++ exception \"%s\" with type \"%s\" "
83  "while processing timer queue, at %s\n",
84  pExceptionContext, pExceptionTypeName, date );
85 }
86 
87 
88 void timerQueueActive :: run ()
89 {
90  epics::atomic::set(this->exitFlag, 0);
91  while ( ! this->terminateFlag ) {
92  try {
93  double delay = this->queue.process ( epicsTime::getCurrent() );
94  debugPrintf ( ( "timer thread sleeping for %g sec (max)\n", delay ) );
95  this->rescheduleEvent.wait ( delay );
96  }
97  catch ( std :: exception & except ) {
98  _printLastChanceExceptionMessage (
99  typeid ( except ).name (), except.what () );
100  epicsThreadSleep ( 10.0 );
101  }
102  catch ( ... ) {
103  _printLastChanceExceptionMessage (
104  "catch ( ... )", "Non-standard C++ exception" );
105  epicsThreadSleep ( 10.0 );
106  }
107  }
108  epics::atomic::set(this->exitFlag, 1);
109  this->exitEvent.signal (); // no access to queue after exitEvent signal
110 }
111 
113 {
114  return this->queue.createTimer();
115 }
116 
118 {
119  return this->queue.createTimerForC ( pCallback, pArg );
120 }
121 
122 void timerQueueActive::reschedule ()
123 {
124  this->rescheduleEvent.signal ();
125 }
126 
127 double timerQueueActive::quantum ()
128 {
129  return this->sleepQuantum;
130 }
131 
132 void timerQueueActive::show ( unsigned int level ) const
133 {
134  printf ( "EPICS threaded timer queue at %p\n",
135  static_cast <const void *> ( this ) );
136  if ( level > 0u ) {
137  // specifying level one here avoids recursive
138  // show callback
139  this->thread.show ( 1u );
140  this->queue.show ( level - 1u );
141  printf ( "reschedule event\n" );
142  this->rescheduleEvent.show ( level - 1u );
143  printf ( "exit event\n" );
144  this->exitEvent.show ( level - 1u );
145  printf ( "exitFlag = %c, terminateFlag = %c\n",
146  epics::atomic::get(this->exitFlag) ? 'T' : 'F',
147  this->terminateFlag ? 'T' : 'F' );
148  }
149 }
150 
151 epicsTimerQueue & timerQueueActive::getEpicsTimerQueue ()
152 {
153  return static_cast < epicsTimerQueue &> ( * this );
154 }
155 
void show(unsigned int level) const
Definition: timerQueue.cpp:214
LIBCOM_API double epicsStdCall epicsThreadSleepQuantum(void)
Query a value approximating the OS timer/scheduler resolution.
Definition: osdThread.c:981
#define printf
Definition: epicsStdio.h:41
epicsTimer & createTimer()
Definition: timerQueue.cpp:204
reference getReference()
epicsSingleton< timerQueueActiveMgr > timerQueueMgrEPICS
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass size)
Definition: osdThread.c:466
epicsTimerForC & createTimerForC(epicsTimerCallback pCallback, void *pArg)
Definition: timerQueue.cpp:209
void(* epicsTimerCallback)(void *pPrivate)
Definition: epicsTimer.h:134
char * allocate(unsigned int n)
Definition: antelope.c:230
void show(unsigned int level) const
epicsSingleton< timerQueueActiveMgr >::reference RefMgr
Definition: timerPrivate.h:132
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
void date(const char *format)
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
Definition: caget.c:48
epicsTimer & createTimer()
#define debugPrintf(argsInParen)
Definition: iocinf.h:30
epicsTimerForC & createTimerForC(epicsTimerCallback pCallback, void *pArg)
timerQueueActive(RefMgr &, bool okToShare, unsigned priority)
double process(const epicsTime &currentTime)
Definition: timerQueue.cpp:78
#define false
Definition: flexdef.h:85