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