blob: 3aca1671c5bb8bd1cb51031433f0adf55963ed95 [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001//
2// Thread.h: header file
3//
4// Copyright (C) Walter E. Capers. All rights reserved
5//
6// This source is free to use as you like. If you make
7// any changes please keep me in the loop. Email them to
8// walt.capers@comcast.net.
9//
10// PURPOSE:
11//
12// To implement Win32 threading as a C++ object
13//
14// REVISIONS
15// =======================================================
16// Date: 10.24.07
17// Name: Walter E. Capers
18// Description: File creation
19//
20// Date: 10.24.07 11:49 am
21// Name: Walter E. Capers
22// Description: Added SetIdle function to allow the idle time to be altered
23// independent of the SetThreadType member function.
24// Date: 10.31.07
25// Name: Walter E. Capers
26// Description: Added support for beginthreadex
27// To use compile with -DUSE_BEGIN_THREAD
28//
29//
30
31#ifndef THREAD_CLASS
32#define THREAD_CLASS
33
34#ifndef WINDOWS
35#if defined(_WIN32) || defined(_WIN64)
36#define WINDOWS
37#endif
38#endif
39#ifdef __APPLE__
40#define VMS
41#endif
42
43#ifndef WINDOWS
44#include <stdio.h>
45#include <string.h>
46//#include <malloc.h>
47#include <memory.h>
48#include <pthread.h>
49#include <stdlib.h>
50#include <time.h>
51#include <errno.h>
52typedef unsigned char BOOL;
53#define TRUE 1
54#define FALSE 0
55typedef long DWORD;
56typedef void *LPVOID;
57#else
58#include "afx.h"
59/* #include <windows.h> */
60#include <stdio.h>
61#endif
62
63#if defined(AS400) || defined(OS400)
64typedef pthread_id_np_t ThreadId_t;
65#elif defined(VMS)
66typedef pthread_t ThreadId_t;
67#else
68#ifdef USE_BEGIN_THREAD
69typedef unsigned ThreadId_t;
70#else
71typedef DWORD ThreadId_t;
72#endif
73#endif
74
75#include <common/MutexClass.h>
76#include <common/EventClass.h>
77
78#define QUEUE_SIZE 100
79#define DEFAULT_STACK_SIZE 0
80#ifndef WINDOWS
81void Sleep( unsigned int mseconds);
82#endif
83
84#ifndef ASSERT
85#if defined(DEBUG) || defined(_DEBUG)
86#define ASSERT(test) if( !(test) ) { \
87 fprintf(stderr,"\nASSERT(%s) FAILS, %s line %d\n",#test,__FILE__, __LINE__); exit(0);}
88#else
89#define ASSERT(test)
90#endif
91#endif
92
93
94typedef enum {
95 ThreadStateBusy, // thread is currently handling a task
96 ThreadStateWaiting, // thread is waiting for something to do
97 ThreadStateDown, // thread is not running
98 ThreadStateShuttingDown, // thread is in the process of shutting down
99 ThreadStateFault // an error has occured and the thread could not
100 // be launched
101} ThreadState_t;
102
103typedef enum {
104 ThreadTypeHomogeneous,
105 ThreadTypeSpecialized,
106 ThreadTypeIntervalDriven,
107 ThreadTypeNotDefined } ThreadType_t;
108
109
110typedef enum {
111 TaskStatusNotSubmitted,
112 TaskStatusWaitingOnQueue,
113 TaskStatusBeingProcessed,
114 TaskStatusCompleted } TaskStatus_t;
115
116class CTask
117{
118private:
119 TaskStatus_t m_state;
120 ThreadId_t m_dwThread;
121public:
122 CMutexClass m_mutex;
123
124 void SetTaskStatus(TaskStatus_t state)
125 {
126 m_mutex.Lock();
127 m_state=state;
128 m_mutex.Unlock();
129 }
130
131 void SetId(ThreadId_t *pid)
132 {
133 memcpy(&m_dwThread,pid,sizeof(ThreadId_t));
134 }
135
136 /**
137 *
138 * Wait
139 * waits for upto timeoutSeconds for a task
140 * to complete
141 *
142 **/
143 BOOL Wait(int timeoutSeconds)
144 {
145 timeoutSeconds = timeoutSeconds * 1000;
146 if( Status() != TaskStatusCompleted &&
147 timeoutSeconds > 0 )
148 {
149 Sleep(100);
150 timeoutSeconds = timeoutSeconds - 100;
151 }
152 if( Status() == TaskStatusCompleted ) return TRUE;
153 return FALSE;
154 }
155
156 /**
157 *
158 * Status
159 * returns current state of a task
160 *
161 **/
162 TaskStatus_t Status()
163 {
164 TaskStatus_t state ;
165
166 m_mutex.Lock();
167 state = m_state;
168 m_mutex.Unlock();
169 return state;
170 }
171
172 void Thread(ThreadId_t *pId)
173 {
174 memcpy(pId,&m_dwThread,sizeof(ThreadId_t));
175 }
176
177 CTask(){m_state=TaskStatusNotSubmitted; memset(&m_dwThread,0,sizeof(ThreadId_t)); }
178 ~CTask(){}
179 virtual BOOL Task()=0;
180};
181
182
183class CThread
184#ifdef WINDOWS
185 : public CObject // use CObject as a base class so object can be used in lists and
186 // object arrays
187#endif
188{
189private:
190 CEventClass m_event; // event controller
191 int m_StopTimeout; // specifies a timeout value for stop
192 // if a thread fails to stop within m_StopTimeout
193 // seconds an exception is thrown
194
195 BOOL m_bRunning; // set to TRUE if thread is running
196#ifdef WINDOWS
197 HANDLE m_thread; // thread handle
198#else
199 pthread_t m_thread; // thread handle
200#endif
201 ThreadId_t m_dwId; // id of this thread
202 LPVOID *m_lppvQueue; // task que
203 unsigned int m_chQueue; // que depth
204 unsigned int m_queuePos; // current que possition
205 LPVOID m_lpvProcessor; // data which is currently being processed
206 ThreadState_t m_state; // current state of thread see thread state data
207 // structure.
208 DWORD m_dwIdle; // used for Sleep periods
209 ThreadType_t m_type;
210 DWORD m_stackSize; // thread stack size
211#define NO_ERRORS 0
212#define MUTEX_CREATION 0x01
213#define EVENT_CREATION 0x02
214#define THREAD_CREATION 0x04
215#define UNKNOWN 0x08
216#define ILLEGAL_USE_OF_EVENT 0x10
217#define MEMORY_FAULT 0x20
218#define EVENT_AND_TYPE_DONT_MATCH 0x40
219#define STACK_OVERFLOW 0x80
220#define STACK_EMPTY 0x100
221#define STACK_FULL 0x200
222
223 DWORD m_dwObjectCondition;
224 BOOL Push(LPVOID lpv);
225 BOOL Pop();
226 BOOL Empty();
227public:
228 /**
229 *
230 * user definable member functions
231 *
232 **/
233 CMutexClass m_mutex; // mutex that protects threads internal data
234
235 virtual BOOL OnTask(LPVOID lpvData); // called when an event occurs
236 virtual BOOL OnTask(); // called when a time interval has elapsed
237
238 CThread(void);
239 ~CThread(void);
240#ifdef WINDOWS
241#ifdef USE_BEGIN_THREAD
242 friend unsigned __stdcall _THKERNEL(LPVOID lpvData);
243#else
244 friend DWORD WINAPI _THKERNEL( LPVOID lpvData );
245#endif
246#else
247 friend LPVOID _THKERNEL(LPVOID lpvData);
248#endif
249 BOOL FromSameThread();
250 float PercentCapacity();
251 void WaitTillExit();
252 BOOL KernelProcess();
253 BOOL Event(LPVOID lpvData=NULL);
254 BOOL Event(CTask *pvTask);
255 void SetOnStopTimeout(int seconds ) { m_StopTimeout = seconds; }
256 BOOL SetQueueSize( unsigned int ch );
257 BOOL Stop();
258 BOOL Start();
259 void GetId(ThreadId_t *pId) { memcpy(pId,&m_dwId,sizeof(ThreadId_t)); } // returns thread id
260 ThreadState_t ThreadState();
261 BOOL PingThread(DWORD dwTimeout=0);
262 BOOL AtCapacity();
263#ifdef WINDOWS
264 void SetPriority(DWORD dwPriority=THREAD_PRIORITY_NORMAL);
265#else
266 void SetPriority(DWORD dwPriority=0);
267#endif
268 DWORD GetErrorFlags() { return m_dwObjectCondition; } // returns state of object
269 void SetThreadType(ThreadType_t typ=ThreadTypeNotDefined,DWORD dwIdle=100);
270 void SetIdle(DWORD dwIdle=100);
271 unsigned int GetEventsPending();
272 static BOOL ThreadIdsEqual(ThreadId_t *p1,
273 ThreadId_t *p2)
274 {
275#if defined(AS400)||defined(OS400)
276 return(( memcmp(p1,p2,sizeof(ThreadId_t))==0)?TRUE:FALSE);
277#elif defined(VMS)
278 return (( pthread_equal(*p1,*p2) )?TRUE:FALSE );
279#else
280 return ((*p1 == *p2)?TRUE:FALSE);
281#endif
282
283 }
284
285 static ThreadId_t ThreadId()
286 {
287 ThreadId_t thisThreadsId ;
288#if defined(AS400) || defined(OS400)
289 pthread_t thread;
290#endif
291
292#ifdef WINDOWS
293 thisThreadsId = (ThreadId_t)GetCurrentThreadId();
294#else
295
296#if defined(AS400) || defined(OS400)
297 thread = pthread_self();
298 pthread_getunique_np(&thread,&thisThreadsId);
299#elif defined(ALPHA) || defined(DEC) || defined(VMS)
300#ifdef VMS
301 thisThreadsId = pthread_self();
302#else
303 thisThreadsId = pthread_getsequence_np(pthread_self());
304#endif
305#else
306 thisThreadsId = pthread_self();
307#endif
308#endif
309 return thisThreadsId;
310 }
311
312
313};
314#endif
315