Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
270 johboh 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__