$search
00001 // 00002 // Thread.h: header file 00003 // 00004 // Copyright (C) Walter E. Capers. All rights reserved 00005 // 00006 // This source is free to use as you like. If you make 00007 // any changes please keep me in the loop. Email them to 00008 // walt.capers@comcast.net. 00009 // 00010 // PURPOSE: 00011 // 00012 // To implement Win32 threading as a C++ object 00013 // 00014 // REVISIONS 00015 // ======================================================= 00016 // Date: 10.24.07 00017 // Name: Walter E. Capers 00018 // Description: File creation 00019 // 00020 // Date: 10.24.07 11:49 am 00021 // Name: Walter E. Capers 00022 // Description: Added SetIdle function to allow the idle time to be altered 00023 // independent of the SetThreadType member function. 00024 // Date: 00025 // Name: 00026 // Description: 00027 // 00028 // 00029 00030 #ifndef THREAD_CLASS 00031 #define THREAD_CLASS 00032 00033 #ifndef WINDOWS 00034 #if defined(WIN32) || defined(WIN64) 00035 #define WINDOWS 00036 #endif 00037 #endif 00038 00039 #ifndef WINDOWS 00040 #include <stdio.h> 00041 #include <malloc.h> 00042 #include <memory.h> 00043 #include <pthread.h> 00044 #include <stdlib.h> 00045 #include <time.h> 00046 #include <errno.h> 00047 typedef unsigned char BOOL; 00048 #ifndef TRUE 00049 #define TRUE 1 00050 #endif 00051 #ifndef FALSE 00052 #define FALSE 0 00053 #endif 00054 typedef long DWORD; 00055 typedef void *LPVOID; 00056 #else 00057 #include "afx.h" 00058 #include <windows.h> 00059 #include <stdio.h> 00060 #endif 00061 00062 00063 #if defined(AS400) || defined(OS400) 00064 typedef pthread_id_np_t ThreadId_t; 00065 #elif defined(VMS) 00066 typedef pthread_t ThreadId_t; 00067 #else 00068 typedef DWORD ThreadId_t; 00069 #endif 00070 00071 #include <blort/ThreadObject/MutexClass.h> 00072 #include <blort/ThreadObject/EventClass.h> 00073 00074 #define QUE_SIZE 100 00075 #define DEFAULT_STACK_SIZE 0 00076 #ifndef WINDOWS 00077 void Sleep( unsigned int mseconds); 00078 #endif 00079 00080 typedef enum { 00081 ThreadStateBusy, // thread is currently handling a task 00082 ThreadStateWaiting, // thread is waiting for something to do 00083 ThreadStateDown, // thread is not running 00084 ThreadStateShuttingDown, // thread is in the process of shutting down 00085 ThreadStateFault // an error has occured and the thread could not 00086 // be launched 00087 } ThreadState_t; 00088 00089 typedef enum { 00090 ThreadTypeEventDriven, 00091 ThreadTypeIntervalDriven } ThreadType_t; 00092 00093 typedef enum { 00094 TaskStatusNotSubmitted, 00095 TaskStatusWaitingOnQueue, 00096 TaskStatusBeingProcessed, 00097 TaskStatusCompleted } TaskStatus_t; 00098 00099 class CTask 00100 { 00101 private: 00102 TaskStatus_t m_state; 00103 ThreadId_t m_dwThread; 00104 public: 00105 CMutexClass m_mutex; 00106 00107 void SetTaskStatus(TaskStatus_t state) 00108 { 00109 m_mutex.Lock(); 00110 m_state=state; 00111 m_mutex.Unlock(); 00112 } 00113 00114 void SetId(ThreadId_t *pid) 00115 { 00116 memcpy(&m_dwThread,pid,sizeof(ThreadId_t)); 00117 } 00118 00126 BOOL Wait(int timeoutSeconds) 00127 { 00128 timeoutSeconds = timeoutSeconds * 1000; 00129 if( Status() != TaskStatusCompleted && 00130 timeoutSeconds > 0 ) 00131 { 00132 Sleep(100); 00133 timeoutSeconds = timeoutSeconds - 100; 00134 } 00135 if( Status() == TaskStatusCompleted ) return TRUE; 00136 return FALSE; 00137 } 00138 00145 TaskStatus_t Status() 00146 { 00147 TaskStatus_t state ; 00148 00149 m_mutex.Lock(); 00150 state = m_state; 00151 m_mutex.Unlock(); 00152 return state; 00153 } 00154 00155 void Thread(ThreadId_t *pId) 00156 { 00157 memcpy(pId,&m_dwThread,sizeof(ThreadId_t)); 00158 } 00159 00160 CTask(){m_state=TaskStatusNotSubmitted; memset(&m_dwThread,0,sizeof(ThreadId_t)); } 00161 ~CTask(){} 00162 virtual BOOL Task()=0; 00163 }; 00164 00165 00166 class CThread 00167 #ifdef WINDOWS 00168 : public CObject // use CObject as a base class so object can be used in lists and 00169 // object arrays 00170 #endif 00171 { 00172 private: 00173 CEventClass m_event; // event controller 00174 00175 BOOL m_bRunning; // set to TRUE if thread is running 00176 #ifdef WINDOWS 00177 HANDLE m_thread; // thread handle 00178 #else 00179 pthread_t m_thread; // thread handle 00180 #endif 00181 ThreadId_t m_dwId; // id of this thread 00182 LPVOID *m_lppvQue; // task que 00183 unsigned int m_chQue; // que depth 00184 unsigned int m_quePos; // current que possition 00185 LPVOID m_lpvProcessor; // data which is currently being processed 00186 ThreadState_t m_state; // current state of thread see thread state data 00187 // structure. 00188 DWORD m_dwIdle; // used for Sleep periods 00189 ThreadType_t m_type; 00190 DWORD m_stackSize; // thread stack size 00191 #define NO_ERRORS 0 00192 #define MUTEX_CREATION 0x01 00193 #define EVENT_CREATION 0x02 00194 #define THREAD_CREATION 0x04 00195 #define UNKNOWN 0x08 00196 #define ILLEGAL_USE_OF_EVENT 0x10 00197 #define MEMORY_FAULT 0x20 00198 DWORD m_dwObjectCondition; 00199 BOOL Push(LPVOID lpv); 00200 BOOL Pop(); 00201 BOOL Empty(); 00202 public: 00208 CMutexClass m_mutex; // mutex that protects threads internal data 00209 00210 virtual BOOL OnTask(LPVOID lpvData); // called when an event occurs 00211 virtual BOOL OnTask(); // called when a time interval has elapsed 00212 00213 CThread(void); 00214 ~CThread(void); 00215 #ifdef WINDOWS 00216 friend DWORD WINAPI _THKERNEL( LPVOID lpvData ); 00217 #else 00218 friend LPVOID _THKERNEL(LPVOID lpvData); 00219 #endif 00220 BOOL KernelProcess(); 00221 BOOL Event(LPVOID lpvData=NULL); 00222 BOOL Event(CTask *pvTask); 00223 void Stop(); 00224 BOOL Start(); 00225 void GetId(ThreadId_t *pId) { memcpy(pId,&m_dwId,sizeof(ThreadId_t)); } // returns thread id 00226 ThreadState_t ThreadState(); 00227 BOOL PingThread(DWORD dwTimeout=0); 00228 #ifdef WINDOWS 00229 void SetPriority(DWORD dwPriority=THREAD_PRIORITY_NORMAL); 00230 #else 00231 void SetPriority(DWORD dwPriority=0); 00232 #endif 00233 DWORD GetErrorFlags() { return m_dwObjectCondition; } // returns state of object 00234 void SetThreadType(ThreadType_t typ=ThreadTypeEventDriven,DWORD dwIdle=100); 00235 void SetIdle(DWORD dwIdle=100); 00236 unsigned int GetEventsPending(); 00237 static BOOL ThreadIdsEqual(ThreadId_t *p1, 00238 ThreadId_t *p2) 00239 { 00240 #if defined(AS400)||defined(OS400) 00241 return(( memcmp(p1,p2,sizeof(ThreadId_t))==0)?TRUE:FALSE); 00242 #elif defined(VMS) 00243 return (( pthread_equal(*p1,*p2) )?TRUE:FALSE ); 00244 #else 00245 return ((*p1 == *p2)?TRUE:FALSE); 00246 #endif 00247 00248 } 00249 00250 static ThreadId_t ThreadId() 00251 { 00252 ThreadId_t thisThreadsId ; 00253 #if defined(AS400) || defined(OS400) 00254 pthread_t thread; 00255 #endif 00256 00257 #ifdef WINDOWS 00258 thisThreadsId = (ThreadId_t)GetCurrentThreadId(); 00259 #else 00260 00261 #if defined(AS400) || defined(OS400) 00262 thread = pthread_self(); 00263 pthread_getunique_np(&thread,&thisThreadsId); 00264 #elif defined(ALPHA) || defined(DEC) || defined(VMS) 00265 #ifdef VMS 00266 thisThreadsId = pthread_self(); 00267 #else 00268 thisThreadsId = pthread_getsequence_np(pthread_self()); 00269 #endif 00270 #else 00271 thisThreadsId = pthread_self(); 00272 #endif 00273 #endif 00274 return thisThreadsId; 00275 } 00276 00277 00278 }; 00279 #endif 00280