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 {
00241 try
00242 {
00243
00244 if (!dwInterval)
00245 {
00246
00247 ReportError("Start","Invalid interval!");
00248
00249
00250 return FALSE;
00251 }
00252
00253
00254 if (m_dwInterval ||
00255 m_pEnterEvent ||
00256 m_pExitEvent)
00257 {
00258
00259 ReportError("Start","Already running!");
00260
00261
00262 return FALSE;
00263 }
00264
00265
00266 m_bAbort=FALSE;
00267
00268
00269 m_pEnterEvent=COSManager::CreateEvent();
00270 m_pExitEvent=COSManager::CreateEvent();
00271
00272
00273 m_lpData=lpData;
00274
00275
00276 m_dwInterval=dwInterval;
00277 m_bWaitOneInterval=bWaitOneInterval;
00278
00279
00280 m_pThread->SetAutoDelete(TRUE);
00281
00282
00283 m_pThread->Start((LPVOID)this);
00284
00285
00286 if (m_pEnterEvent->Wait(m_dwThreadTimeout) ||
00287 m_bAbort)
00288 {
00289
00290 if (m_bAbort)
00291 ReportError("Start","User aborted!");
00292 else
00293 ReportError("Start","Timeout waiting for thread!");
00294
00295
00296 delete m_pThread;
00297 m_pThread=COSManager::CreateThread(PeriodicThread);
00298
00299
00300 delete m_pEnterEvent;
00301 m_pEnterEvent=NULL;
00302
00303 delete m_pExitEvent;
00304 m_pExitEvent=NULL;
00305
00306
00307 return FALSE;
00308 }
00309 else
00310 return TRUE;
00311 }
00312 ERROR_HANDLER_RETURN("Start",FALSE)
00313 }
00314
00315 BOOL CPeriodicThread::Stop()
00316 {
00317 try
00318 {
00319 if (m_bDestructor)
00320 if (!m_pEnterEvent ||
00321 !m_pExitEvent)
00322 {
00323
00324 delete m_pThread;
00325
00326
00327 return TRUE;
00328 }
00329 else
00330 ;
00331 else
00332
00333 if (!m_pEnterEvent ||
00334 !m_pExitEvent)
00335 {
00336
00337 ReportError("Stop","Not running!");
00338
00339
00340 return FALSE;
00341 }
00342
00343
00344 if (!m_bAbort)
00345 {
00346
00347 DWORD dwThreadID;
00348 dwThreadID=m_pThread->GetThreadID();
00349
00350
00351 m_pExitEvent->Set();
00352
00353
00354 if (GetCurrentThreadId()!=dwThreadID &&
00355 m_pEnterEvent->Wait(m_dwThreadTimeout))
00356 {
00357
00358 ReportError("Stop","Timeout waiting for thread!");
00359
00360
00361 delete m_pThread;
00362 }
00363 }
00364
00365
00366 m_pThread=NULL;
00367
00368
00369 if (!m_bDestructor)
00370 m_pThread=COSManager::CreateThread(PeriodicThread);
00371
00372
00373 delete m_pEnterEvent;
00374 m_pEnterEvent=NULL;
00375
00376 delete m_pExitEvent;
00377 m_pExitEvent=NULL;
00378
00379
00380 m_dwInterval=0;
00381
00382
00383 return TRUE;
00384 }
00385 ERROR_HANDLER_RETURN("Stop",FALSE)
00386 }
00387
00388 void CPeriodicThread::SetThreadTimeout(DWORD dwTimeout)
00389 {
00390 try
00391 {
00392
00393 m_dwThreadTimeout=dwTimeout;
00394 }
00395 ERROR_HANDLER("SetThreadTimeout")
00396 }
00397
00398 CGenericThread* CPeriodicThread::GetThread()const
00399 {
00400 return m_pThread;
00401 }
00402
00403 void CPeriodicThread::SetPriority(CGenericThread::ThreadPriority aPriority)
00404 {
00405 try
00406 {
00407
00408 m_pThread->SetPriority(aPriority);
00409 }
00410 ERROR_HANDLER("SetPriority")
00411 }
00412
00413 KOMODIA_NAMESPACE_END