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 {
00063 try
00064 {
00065
00066 SetName(CPeriodicThread_Class);
00067
00068
00069 m_pThread=COSManager::CreateThread(PeriodicThread);
00070 }
00071 ERROR_HANDLER("CPeriodicThread")
00072 }
00073
00074 CPeriodicThread::~CPeriodicThread()
00075 {
00076 try
00077 {
00078
00079 m_bDestructor=TRUE;
00080
00081
00082 Stop();
00083 }
00084 ERROR_HANDLER("~CPeriodicThread")
00085 }
00086
00087 DWORD CPeriodicThread::PeriodicThread(LPVOID lpData)
00088 {
00089 try
00090 {
00091
00092 CPeriodicThread* pClass;
00093 pClass=(CPeriodicThread*)lpData;
00094
00095
00096 BOOL bExit;
00097 bExit=FALSE;
00098
00099
00100 try
00101 {
00102 if (!(*pClass->m_pUserProc)(tsStart,
00103 pClass->m_lpData))
00104
00105 bExit=TRUE;
00106 }
00107 catch (...)
00108 {
00109 bExit=TRUE;
00110 }
00111
00112
00113 if (bExit)
00114 pClass->m_bAbort=TRUE;
00115
00116
00117 if (pClass->m_pEnterEvent)
00118 pClass->m_pEnterEvent->Set();
00119 else
00120 return FALSE;
00121
00122
00123 if (bExit)
00124 return FALSE;
00125
00126
00127 BOOL bFirstRun;
00128 bFirstRun=TRUE;
00129
00130
00131 while (1)
00132 {
00133
00134 if (!pClass->m_dwInterval)
00135 {
00136
00137 ReportStaticError(CPeriodicThread_Class,"PeriodicThread","Zero interval!");
00138
00139
00140 break;
00141 }
00142
00143
00144 if (bFirstRun)
00145
00146 bFirstRun=FALSE;
00147 else
00148
00149 if (!pClass->m_pExitEvent->Wait(pClass->m_dwInterval))
00150 break;
00151
00152
00153 try
00154 {
00155 if (!(*pClass->m_pUserProc)(tsBody,
00156 pClass->m_lpData))
00157
00158 bExit=TRUE;
00159 }
00160 catch (...)
00161 {
00162 bExit=TRUE;
00163 }
00164
00165
00166 if (bExit)
00167 {
00168
00169 pClass->m_bAbort=TRUE;
00170
00171
00172 return FALSE;
00173 }
00174 }
00175
00176
00177 BOOL bValue;
00178
00179
00180 try
00181 {
00182 bValue=(*pClass->m_pUserProc)(tsEnd,
00183 pClass->m_lpData);
00184 }
00185 catch (...)
00186 {
00187 bValue=FALSE;
00188 }
00189
00190
00191 pClass->m_pEnterEvent->Set();
00192
00193
00194 return bValue;
00195 }
00196 ERROR_HANDLER_STATIC_RETURN(CPeriodicThread_Class,"PeriodicThread",FALSE)
00197 }
00198
00199 BOOL CPeriodicThread::Start(DWORD dwInterval,
00200 LPVOID lpData)
00201 {
00202 try
00203 {
00204
00205 if (!dwInterval)
00206 {
00207
00208 ReportError("Start","Invalid interval!");
00209
00210
00211 return FALSE;
00212 }
00213
00214
00215 if (m_dwInterval ||
00216 m_pEnterEvent ||
00217 m_pExitEvent)
00218 {
00219
00220 ReportError("Start","Already running!");
00221
00222
00223 return FALSE;
00224 }
00225
00226
00227 m_bAbort=FALSE;
00228
00229
00230 m_pEnterEvent=COSManager::CreateEvent();
00231 m_pExitEvent=COSManager::CreateEvent();
00232
00233
00234 m_lpData=lpData;
00235
00236
00237 m_dwInterval=dwInterval;
00238
00239
00240 m_pThread->SetAutoDelete(TRUE);
00241
00242
00243 m_pThread->Start((LPVOID)this);
00244
00245
00246 if (m_pEnterEvent->Wait(m_dwThreadTimeout) ||
00247 m_bAbort)
00248 {
00249
00250 if (m_bAbort)
00251 ReportError("Start","User aborted!");
00252 else
00253 ReportError("Start","Timeout waiting for thread!");
00254
00255
00256 delete m_pThread;
00257 m_pThread=COSManager::CreateThread(PeriodicThread);
00258
00259
00260 delete m_pEnterEvent;
00261 m_pEnterEvent=NULL;
00262
00263 delete m_pExitEvent;
00264 m_pExitEvent=NULL;
00265
00266
00267 return FALSE;
00268 }
00269 else
00270 return TRUE;
00271 }
00272 ERROR_HANDLER_RETURN("Start",FALSE)
00273 }
00274
00275 BOOL CPeriodicThread::Stop()
00276 {
00277 try
00278 {
00279 if (m_bDestructor)
00280 if (!m_pEnterEvent ||
00281 !m_pExitEvent)
00282 {
00283
00284 delete m_pThread;
00285
00286
00287 return TRUE;
00288 }
00289 else
00290 ;
00291 else
00292
00293 if (!m_pEnterEvent ||
00294 !m_pExitEvent)
00295 {
00296
00297 ReportError("Stop","Not running!");
00298
00299
00300 return FALSE;
00301 }
00302
00303
00304 if (!m_bAbort)
00305 {
00306
00307 DWORD dwThreadID;
00308 dwThreadID=m_pThread->GetThreadID();
00309
00310
00311 m_pExitEvent->Set();
00312
00313
00314 if (GetCurrentThreadId()!=dwThreadID &&
00315 m_pEnterEvent->Wait(m_dwThreadTimeout))
00316 {
00317
00318 ReportError("Stop","Timeout waiting for thread!");
00319
00320
00321 delete m_pThread;
00322 }
00323 }
00324
00325
00326 m_pThread=NULL;
00327
00328
00329 if (!m_bDestructor)
00330 m_pThread=COSManager::CreateThread(PeriodicThread);
00331
00332
00333 delete m_pEnterEvent;
00334 m_pEnterEvent=NULL;
00335
00336 delete m_pExitEvent;
00337 m_pExitEvent=NULL;
00338
00339
00340 m_dwInterval=0;
00341
00342
00343 return TRUE;
00344 }
00345 ERROR_HANDLER_RETURN("Stop",FALSE)
00346 }
00347
00348 void CPeriodicThread::SetThreadTimeout(DWORD dwTimeout)
00349 {
00350 try
00351 {
00352
00353 m_dwThreadTimeout=dwTimeout;
00354 }
00355 ERROR_HANDLER("SetThreadTimeout")
00356 }
00357
00358 CGenericThread* CPeriodicThread::GetThread()const
00359 {
00360 return m_pThread;
00361 }
00362
00363 void CPeriodicThread::SetPriority(CGenericThread::ThreadPriority aPriority)
00364 {
00365 try
00366 {
00367
00368 m_pThread->SetPriority(aPriority);
00369 }
00370 ERROR_HANDLER("SetPriority")
00371 }
00372
00373 KOMODIA_NAMESPACE_END