Subversion Repositories HomeAutomation

Rev

Rev 270 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. #ifndef __THREAD_H__
  2. #define __THREAD_H__
  3.  
  4. class CThread
  5. {
  6. public:
  7.         /*
  8.          *  Info: Default Constructor
  9.          */
  10.         CThread()
  11.         {
  12.             m_pThreadFunc = CThread::EntryPoint; // Can call Detach() also.
  13.         }
  14.  
  15.         /*
  16.          *  Info: Plug Constructor
  17.          *
  18.          *  Use this to migrate/port existing worker threads to objects immediately
  19.          *  Although you lose the benefits of ThreadCTOR and ThreadDTOR.
  20.          */
  21.         CThread(LPTHREAD_START_ROUTINE lpExternalRoutine)
  22.         {
  23.             Attach(lpExternalRoutine);
  24.         }
  25.  
  26.         /*
  27.          *  Info: Default Destructor
  28.          *
  29.          *  I think it is wise to destroy the thread even if it is running,
  30.          *  when the main thread reaches here.
  31.          */
  32.         ~CThread()
  33.         {
  34.             if ( m_ThreadCtx.m_hThread )
  35.                 Stop(true);
  36.         }
  37.         /*
  38.          *  Info: Starts the thread.
  39.          * 
  40.          *  This function starts the thread pointed by m_pThreadFunc with default attributes
  41.          */
  42.         DWORD Start( void* arg = NULL )
  43.         {
  44.             m_ThreadCtx.m_pUserData = arg;
  45.             m_ThreadCtx.m_hThread = CreateThread(NULL, 0, m_pThreadFunc, this, 0, &m_ThreadCtx.m_dwTID);
  46.             m_ThreadCtx.m_dwExitCode = (DWORD)-1;
  47.  
  48.             return GetLastError();
  49.         }
  50.  
  51.         /*
  52.          *  Info: Stops the thread.
  53.          * 
  54.          *  This function stops the current thread.
  55.          *  We can force kill a thread which results in a TerminateThread.
  56.          */
  57.         DWORD Stop ( bool bForceKill = false )
  58.         {
  59.             if ( m_ThreadCtx.m_hThread )
  60.             {
  61.                 GetExitCodeThread(m_ThreadCtx.m_hThread, &m_ThreadCtx.m_dwExitCode);
  62.  
  63.                 if ( m_ThreadCtx.m_dwExitCode == STILL_ACTIVE && bForceKill )
  64.                     TerminateThread(m_ThreadCtx.m_hThread, DWORD(-1));
  65.  
  66.                 m_ThreadCtx.m_hThread = NULL;
  67.             }
  68.  
  69.             return m_ThreadCtx.m_dwExitCode;
  70.         }
  71.  
  72.         /*
  73.          *  Info: Starts the thread.
  74.          * 
  75.          *  This function starts the thread pointed by m_pThreadFunc with default attributes
  76.          */
  77.         DWORD GetExitCode() const
  78.         {
  79.             if ( m_ThreadCtx.m_hThread )
  80.                 GetExitCodeThread(m_ThreadCtx.m_hThread, (LPDWORD)&m_ThreadCtx.m_dwExitCode);
  81.             return m_ThreadCtx.m_dwExitCode;
  82.         }
  83.  
  84.         /*
  85.          *  Info: Attaches a Thread Function
  86.          * 
  87.          *  Used primarily for porting but can serve in developing generic thread objects
  88.          */
  89.         void Attach( LPTHREAD_START_ROUTINE lpThreadFunc ){
  90.             m_pThreadFunc = lpThreadFunc;
  91.         }
  92.  
  93.         /*
  94.          *  Info: Detaches the Attached Thread Function
  95.          * 
  96.          *  Detaches the Attached Thread Function, If any.
  97.          *  by resetting the thread function pointer to EntryPoint1
  98.          */
  99.         void  Detach( void ){
  100.             m_pThreadFunc = CThread::EntryPoint;
  101.         }
  102.  
  103. protected:
  104.  
  105.         /*
  106.          *  Info: DONT override this method.
  107.          * 
  108.          *  This function is like a standard template.
  109.          *  Override if you are sure of what you are doing.
  110.          */
  111.         static DWORD WINAPI EntryPoint( LPVOID pArg)
  112.         {
  113.             CThread *pParent = reinterpret_cast<CThread*>(pArg);
  114.  
  115.             pParent->ThreadCtor();
  116.  
  117.             pParent->Run( pParent->m_ThreadCtx.m_pUserData );
  118.  
  119.             pParent->ThreadDtor();
  120.  
  121.             return STILL_ACTIVE;
  122.         }
  123.        
  124.         /*
  125.          *  Info: Override this method.
  126.          * 
  127.          *  This function should contain the body/code of your thread.
  128.          *  Notice the signature is similar to that of any worker thread function
  129.          *  except for the calling convention.
  130.          */
  131.         virtual DWORD Run( LPVOID /* arg */ )
  132.         { return m_ThreadCtx.m_dwExitCode; }
  133.  
  134.         /*
  135.          *  Info: Constructor-like function.
  136.          * 
  137.          *  Will be called by EntryPoint before executing the thread body.
  138.          *  Override this function to provide your extra initialization.
  139.          *
  140.          *  NOTE: do not confuse it with the classes constructor
  141.          */
  142.         virtual void ThreadCtor(){  }
  143.  
  144.         /*
  145.          *  Info: Destructor-like function.
  146.          * 
  147.          *  Will be called by EntryPoint after executing the thread body.
  148.          *  Override this function to provide your extra destruction.
  149.          *
  150.          *  NOTE: do not confuse it with the classes constructor
  151.          */
  152.         virtual void ThreadDtor(){  }
  153.        
  154. private:
  155.         /*
  156.          *  Info: Thread Context Inner Class
  157.          * 
  158.          *  Every thread object needs to be associated with a set of values.
  159.          *  like UserData Pointer, Handle, Thread ID etc.
  160.          *  
  161.          *  NOTE: This class can be enhanced to varying functionalities
  162.          *        eg.,
  163.          *              * Members to hold StackSize
  164.          *              * SECURITY_ATTRIBUTES member.
  165.          */
  166.         class CThreadContext
  167.         {
  168.         public:
  169.             CThreadContext(){
  170.                 memset(this, 0, sizeof(this));
  171.             }
  172.  
  173.             /*
  174.              *  Attributes Section
  175.              */
  176.         public:
  177.             HANDLE m_hThread;                   //  The Thread Handle
  178.             DWORD  m_dwTID;                     //  The Thread ID
  179.             LPVOID m_pUserData;                     //  The user data pointer
  180.             LPVOID m_pParent;                   //  The this pointer of the parent CThread object
  181.             DWORD  m_dwExitCode;                //  The Exit Code of the thread
  182.         };
  183.  
  184.         /*
  185.          *  Attributes Section
  186.          */
  187. protected:
  188.         /*
  189.          *  Info: Members of CThread
  190.          */
  191.         CThreadContext          m_ThreadCtx;    //  The Thread Context member
  192.         LPTHREAD_START_ROUTINE  m_pThreadFunc;  //  The Worker Thread Function Pointer
  193. };
  194.  
  195. #endif //__THREAD_H__
  196.