00001
00002
00003
00004
00005 #include <process.h>
00006
00007 #include "thread.hh"
00008
00009 struct W32ThreadData
00010 {
00011 unsigned long handle;
00012 unsigned id;
00013 long defaultPriority;
00014 long currentPriority;
00015 };
00016
00017 const unsigned long Thread::kThreadShutDownTimeout = 60;
00018
00019 static unsigned __stdcall W32ThreadFunc( void *currThread )
00020 {
00021 ((Thread *)currThread)->internalRun();
00022 return(0);
00023 }
00024
00025
00026 Thread::Thread(bool susp) : self_destruct(false), implData((void*)new W32ThreadData)
00027 {
00028 currentPriority = 0;
00029
00030 assert(implData);
00031 cs = System::createCriticalSection();
00032 assert(cs);
00033 cs->enter();
00034
00035 status = kThreadCreated;
00036 suspended = susp;
00037
00038 W32ThreadData &d = *((W32ThreadData *)implData);
00039 status = kThreadCreated;
00040
00041
00042 d.handle = _beginthreadex( NULL, 0, W32ThreadFunc, (LPVOID)this,
00043 suspended ? CREATE_SUSPENDED : 0, &d.id );
00044 if((!d.handle) || suspended) cs->leave();
00045
00046 assert(d.handle);
00047 }
00048
00049 Thread::~Thread()
00050 {
00051 stop( kThreadShutDownTimeout );
00052 if( !stopped() )
00053 {
00054 destroy();
00055 }
00056 CloseHandle( (HANDLE)((W32ThreadData *)implData)->handle );
00057 delete (W32ThreadData *)implData;
00058 delete cs;
00059 }
00060
00061 long Thread::stop( unsigned long timeoutSeconds )
00062 {
00063 cs->enter();
00064 if( status == kThreadRunning )
00065 {
00066 status = kThreadStopping;
00067 }
00068 else
00069 {
00070 cs->leave();
00071 return( kThreadIsNotRunning );
00072 }
00073 cs->leave();
00074
00075 return(join( timeoutSeconds ));
00076 }
00077
00078 long Thread::suspend()
00079 {
00080 cs->enter();
00081 suspended = true;
00082 cs->leave();
00083
00084 if( SuspendThread( (HANDLE)((W32ThreadData *)implData)->handle ) != 0xFFFFFFFF )
00085 {
00086 cs->enter();
00087 suspended = false;
00088 cs->leave();
00089 return(GetLastError());
00090 }
00091 else
00092 {
00093 return(0);
00094 }
00095 }
00096
00097 long Thread::resume()
00098 {
00099 DWORD res;
00100 cs->enter();
00101 suspended = false;
00102 cs->leave();
00103 do
00104 {
00105 res = ResumeThread( (HANDLE)((W32ThreadData *)implData)->handle );
00106 if( res == 0xFFFFFFFF )
00107 {
00108 res = GetLastError();
00109 cs->enter();
00110 suspended = true;
00111 cs->leave();
00112 return(res);
00113 }
00114 }
00115 while( res > 1 );
00116 return(0);
00117 }
00118
00119 long Thread::join( unsigned long timeoutSeconds )
00120 {
00121 DWORD timeout = timeoutSeconds * 1000;
00122
00123
00124 while( (status == kThreadRunning) || (status == kThreadStopping) )
00125 {
00126 DWORD res = WaitForSingleObject(
00127 (HANDLE)((W32ThreadData *)implData)->handle,
00128 50 );
00129 if( res != WAIT_TIMEOUT )
00130 {
00131 if( res == WAIT_FAILED ) return kThreadTimeout;
00132 else return 0;
00133 }
00134 if( timeout < 50 ) return kThreadTimeout;
00135 timeout -= 50;
00136 }
00137
00138 return(0);
00139 }
00140
00141 void Thread::sleep( unsigned long sleepTimeMillisec )
00142 {
00143 Sleep( sleepTimeMillisec );
00144 }
00145
00146 void Thread::yield()
00147 {
00148 Sleep(0);
00149 }
00150
00151 long Thread::destroy()
00152 {
00153 long res;
00154 if( TerminateThread( (HANDLE)((W32ThreadData *)implData)->handle, 3 ) )
00155 {
00156 res = 0;
00157 }
00158 else
00159 {
00160 res = GetLastError();
00161 }
00162
00163 return(res);
00164 }
00165
00166 struct ThreadPriorityStr
00167 {
00168 static ThreadPriorityStr priorities[];
00169 static long normalPriority;
00170 static long len;
00171
00172 static int getNativePriority( long cpPr )
00173 {
00174 int res = cpPr + normalPriority;
00175 if( res < 0 ) res = 0;
00176 if( res >= len ) res = len - 1;
00177 return( priorities[res].w32Priority );
00178 }
00179
00180 int w32Priority;
00181 };
00182
00183
00184 ThreadPriorityStr ThreadPriorityStr::priorities[7] =
00185 {
00186 THREAD_PRIORITY_TIME_CRITICAL,
00187 THREAD_PRIORITY_HIGHEST,
00188 THREAD_PRIORITY_ABOVE_NORMAL,
00189
00190 THREAD_PRIORITY_NORMAL,
00191
00192 THREAD_PRIORITY_BELOW_NORMAL,
00193 THREAD_PRIORITY_LOWEST,
00194 THREAD_PRIORITY_IDLE
00195 };
00196
00197 long ThreadPriorityStr::len = 7;
00198 long ThreadPriorityStr::normalPriority = 3;
00199
00200
00201
00202
00203
00204 long Thread::setPriority( long newPriority )
00205 {
00206 if( newPriority > getMaxPriority() || newPriority < getMinPriority() )
00207 {
00208 return( kThreadInvalidParameter );
00209 }
00210 if( SetThreadPriority( (HANDLE)((W32ThreadData *)implData)->handle,
00211 ThreadPriorityStr::getNativePriority(newPriority) ) )
00212 {
00213 currentPriority = newPriority;
00214 return(0);
00215 }
00216 else
00217 {
00218 return( GetLastError() );
00219 }
00220 }
00221
00222 long Thread::getPriority()
00223 {
00224 return( currentPriority );
00225 }
00226
00227 long Thread::getMaxPriority()
00228 {
00229 return( ThreadPriorityStr::len - (ThreadPriorityStr::normalPriority + 1) );
00230 }
00231
00232 long Thread::getMinPriority()
00233 {
00234 return( -(ThreadPriorityStr::normalPriority) );
00235 }