00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "stdafx.h"
00037 #include "PeriodicThread.h"
00038
00039 #include "ErrorHandlerMacros.h"
00040 #include "GenericEvent.h"
00041 #include "OSManager.h"
00042
00043 #ifdef _MEMORY_DEBUG
00044 #define new DEBUG_NEW
00045 #define malloc DEBUG_MALLOC
00046 static char THIS_FILE[] = __FILE__;
00047 #endif
00048
00049 KOMODIA_NAMESPACE_START
00050
00051 #define CPeriodicThread_Class "CPeriodicThread"
00052
00053 CPeriodicThread::CPeriodicThread(PeriodicThreadProc pProc) : CErrorHandler(),
00054 m_pThread(NULL),
00055 m_pUserProc(pProc),
00056 m_pEnterEvent(NULL),
00057 m_pExitEvent(NULL),
00058 m_dwInterval(0),
00059 m_dwThreadTimeout(20000),
00060 m_bDestructor(FALSE),
00061 m_bAbort(FALSE),
00062 m_pUserProcNoInit(NULL)
00063 {
00064 try
00065 {
00066
00067 SetName(CPeriodicThread_Class);
00068
00069
00070 m_pThread=COSManager::CreateThread(PeriodicThread);
00071 }
00072 ERROR_HANDLER("CPeriodicThread")
00073 }
00074
00075 CPeriodicThread::CPeriodicThread(LPPeriodicThreadProcNoInit pProc) : CErrorHandler(),
00076 m_pThread(NULL),
00077 m_pUserProc(NULL),
00078 m_pEnterEvent(NULL),
00079 m_pExitEvent(NULL),
00080 m_dwInterval(0),
00081 m_dwThreadTimeout(20000),
00082 m_bDestructor(FALSE),
00083 m_bAbort(FALSE),
00084 m_pUserProcNoInit(pProc)
00085 {
00086 try
00087 {
00088
00089 SetName(CPeriodicThread_Class);
00090
00091
00092 m_pThread=COSManager::CreateThread(PeriodicThread);
00093 }
00094 ERROR_HANDLER("CPeriodicThread")
00095 }
00096
00097 CPeriodicThread::~CPeriodicThread()
00098 {
00099 try
00100 {
00101
00102 m_bDestructor=TRUE;
00103
00104
00105 Stop();
00106 }
00107 ERROR_HANDLER("~CPeriodicThread")
00108 }
00109
00110 DWORD CPeriodicThread::PeriodicThread(LPVOID lpData)
00111 {
00112 try
00113 {
00114
00115 CPeriodicThread* pClass;
00116 pClass=(CPeriodicThread*)lpData;
00117
00118
00119 BOOL bExit;
00120 bExit=FALSE;
00121
00122 if (pClass->m_pUserProc)
00123 {
00124
00125 try
00126 {
00127 if (!(*pClass->m_pUserProc)(tsStart,
00128 pClass->m_lpData))
00129
00130 bExit=TRUE;
00131 }
00132 catch (...)
00133 {
00134 bExit=TRUE;
00135 }
00136
00137
00138 if (bExit)
00139 pClass->m_bAbort=TRUE;
00140 }
00141
00142
00143 if (pClass->m_pEnterEvent)
00144 pClass->m_pEnterEvent->Set();
00145 else
00146 return FALSE;
00147
00148
00149 if (bExit)
00150 return FALSE;
00151
00152
00153 BOOL bFirstRun;
00154 bFirstRun=TRUE;
00155
00156
00157 while (1)
00158 {
00159
00160 if (!pClass->m_dwInterval)
00161 {
00162
00163 ReportStaticError(CPeriodicThread_Class,"PeriodicThread","Zero interval!");
00164
00165
00166 break;
00167 }
00168
00169
00170 if (!bFirstRun ||
00171 (bFirstRun &&
00172 pClass->m_bWaitOneInterval))
00173
00174 if (!pClass->m_pExitEvent->Wait(pClass->m_dwInterval))
00175 break;
00176
00177
00178 bFirstRun=FALSE;
00179
00180
00181 try
00182 {
00183 if (pClass->m_pUserProc)
00184 if (!(*pClass->m_pUserProc)(tsBody,
00185 pClass->m_lpData))
00186
00187 bExit=TRUE;
00188 else
00189 ;
00190 else if (!(*pClass->m_pUserProcNoInit)(pClass->m_lpData))
00191
00192 bExit=TRUE;
00193 }
00194 catch (...)
00195 {
00196 bExit=TRUE;
00197 }
00198
00199
00200 if (bExit)
00201 {
00202
00203 pClass->m_bAbort=TRUE;
00204
00205
00206 return FALSE;
00207 }
00208 }
00209
00210
00211 BOOL bValue;
00212 bValue=TRUE;
00213
00214 if (pClass->m_pUserProc)
00215 {
00216
00217 try
00218 {
00219 bValue=(*pClass->m_pUserProc)(tsEnd,
00220 pClass->m_lpData);
00221 }
00222 catch (...)
00223 {
00224 bValue=FALSE;
00225 }
00226 }
00227
00228
00229 pClass->m_pEnterEvent->Set();
00230
00231
00232 return bValue;
00233 }
00234 ERROR_HANDLER_STATIC_RETURN(CPeriodicThread_Class,"PeriodicThread",FALSE)
00235 }
00236
00237 BOOL CPeriodicThread::Start(DWORD dwInterval,
00238 LPVOID lpData,
00239 BOOL bWaitOneInterval,
00240 BOOL bIgnoreEventsOnStartup)
00241 {
00242 try
00243 {
00244
00245 if (!dwInterval)
00246 {
00247
00248 ReportError("Start","Invalid interval!");
00249
00250
00251 return FALSE;
00252 }
00253
00254
00255 if (m_dwInterval ||
00256 m_pEnterEvent ||
00257 m_pExitEvent)
00258 {
00259
00260 ReportError("Start","Already running!");
00261
00262
00263 return FALSE;
00264 }
00265
00266
00267 m_bAbort=FALSE;
00268
00269
00270 m_pEnterEvent=COSManager::CreateEvent();
00271 m_pExitEvent=COSManager::CreateEvent();
00272
00273
00274 m_lpData=lpData;
00275
00276
00277 m_dwInterval=dwInterval;
00278 m_bWaitOneInterval=bWaitOneInterval;
00279
00280
00281 m_pThread->SetAutoDelete(TRUE);
00282
00283
00284 m_pThread->Start((LPVOID)this);
00285
00286
00287 if (!bIgnoreEventsOnStartup &&
00288 (m_pEnterEvent->Wait(m_dwThreadTimeout) ||
00289 m_bAbort))
00290 {
00291
00292 if (m_bAbort)
00293 ReportError("Start","User aborted!");
00294 else
00295 ReportError("Start","Timeout waiting for thread!");
00296
00297
00298 delete m_pThread;
00299 m_pThread=COSManager::CreateThread(PeriodicThread);
00300
00301
00302 delete m_pEnterEvent;
00303 m_pEnterEvent=NULL;
00304
00305 delete m_pExitEvent;
00306 m_pExitEvent=NULL;
00307
00308
00309 return FALSE;
00310 }
00311 else
00312 return TRUE;
00313 }
00314 ERROR_HANDLER_RETURN("Start",FALSE)
00315 }
00316
00317 BOOL CPeriodicThread::Stop()
00318 {
00319 try
00320 {
00321 if (m_bDestructor)
00322 if (!m_pEnterEvent ||
00323 !m_pExitEvent)
00324 {
00325
00326 delete m_pThread;
00327
00328
00329 return TRUE;
00330 }
00331 else
00332 ;
00333 else
00334
00335 if (!m_pEnterEvent ||
00336 !m_pExitEvent)
00337 {
00338
00339 ReportError("Stop","Not running!");
00340
00341
00342 return FALSE;
00343 }
00344
00345
00346 if (!m_bAbort)
00347 {
00348
00349 DWORD dwThreadID;
00350 dwThreadID=m_pThread->GetThreadID();
00351
00352
00353 m_pEnterEvent->Reset();
00354
00355
00356 m_pExitEvent->Set();
00357
00358
00359 if (GetCurrentThreadId()!=dwThreadID &&
00360 m_pEnterEvent->Wait(m_dwThreadTimeout))
00361 {
00362
00363 ReportError("Stop","Timeout waiting for thread!");
00364
00365
00366 delete m_pThread;
00367 }
00368 }
00369
00370
00371 m_pThread=NULL;
00372
00373
00374 if (!m_bDestructor)
00375 m_pThread=COSManager::CreateThread(PeriodicThread);
00376
00377
00378 delete m_pEnterEvent;
00379 m_pEnterEvent=NULL;
00380
00381 delete m_pExitEvent;
00382 m_pExitEvent=NULL;
00383
00384
00385 m_dwInterval=0;
00386
00387
00388 return TRUE;
00389 }
00390 ERROR_HANDLER_RETURN("Stop",FALSE)
00391 }
00392
00393 void CPeriodicThread::SetThreadTimeout(DWORD dwTimeout)
00394 {
00395 try
00396 {
00397
00398 m_dwThreadTimeout=dwTimeout;
00399 }
00400 ERROR_HANDLER("SetThreadTimeout")
00401 }
00402
00403 CGenericThread* CPeriodicThread::GetThread()const
00404 {
00405 return m_pThread;
00406 }
00407
00408 void CPeriodicThread::SetPriority(CGenericThread::ThreadPriority aPriority)
00409 {
00410 try
00411 {
00412
00413 m_pThread->SetPriority(aPriority);
00414 }
00415 ERROR_HANDLER("SetPriority")
00416 }
00417
00418 KOMODIA_NAMESPACE_END