00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "threadWin32Impl.h"
00016 #include "selectThreadImpl.h"
00017
00018 #ifdef THREAD_WIN32_IMPL
00019
00020 #include "thread.h"
00021 #include "pointerTo.h"
00022 #include "config_pipeline.h"
00023
00024 DWORD ThreadWin32Impl::_pt_ptr_index = 0;
00025 bool ThreadWin32Impl::_got_pt_ptr_index = false;
00026
00027
00028
00029
00030
00031
00032 ThreadWin32Impl::
00033 ~ThreadWin32Impl() {
00034 if (thread_cat->is_debug()) {
00035 thread_cat.debug() << "Deleting thread " << _parent_obj->get_name() << "\n";
00036 }
00037
00038 CloseHandle(_thread);
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048 void ThreadWin32Impl::
00049 setup_main_thread() {
00050 _status = S_running;
00051 }
00052
00053
00054
00055
00056
00057
00058 bool ThreadWin32Impl::
00059 start(ThreadPriority priority, bool joinable) {
00060 _mutex.acquire();
00061 if (thread_cat->is_debug()) {
00062 thread_cat.debug() << "Starting " << *_parent_obj << "\n";
00063 }
00064
00065 nassertd(_status == S_new && _thread == 0) {
00066 _mutex.release();
00067 return false;
00068 }
00069
00070 _joinable = joinable;
00071 _status = S_start_called;
00072
00073 if (!_got_pt_ptr_index) {
00074 init_pt_ptr_index();
00075 }
00076
00077
00078
00079 _parent_obj->ref();
00080 _thread =
00081 CreateThread(NULL, 0, &root_func, (void *)this, 0, &_thread_id);
00082
00083 if (_thread_id == 0) {
00084
00085
00086
00087 unref_delete(_parent_obj);
00088 _mutex.release();
00089 return false;
00090 }
00091
00092
00093 switch (priority) {
00094 case TP_low:
00095 SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL);
00096 break;
00097
00098 case TP_high:
00099 SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL);
00100 break;
00101
00102 case TP_urgent:
00103 SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST);
00104 break;
00105
00106 case TP_normal:
00107 default:
00108 SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL);
00109 break;
00110 }
00111
00112 _mutex.release();
00113 return true;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123 void ThreadWin32Impl::
00124 join() {
00125 _mutex.acquire();
00126 nassertd(_joinable && _status != S_new) {
00127 _mutex.release();
00128 return;
00129 }
00130
00131 while (_status != S_finished) {
00132 _cv.wait();
00133 }
00134 _mutex.release();
00135 }
00136
00137
00138
00139
00140
00141
00142 string ThreadWin32Impl::
00143 get_unique_id() const {
00144 ostringstream strm;
00145 strm << GetCurrentProcessId() << "." << _thread_id;
00146
00147 return strm.str();
00148 }
00149
00150
00151
00152
00153
00154
00155 DWORD ThreadWin32Impl::
00156 root_func(LPVOID data) {
00157 TAU_REGISTER_THREAD();
00158 {
00159
00160
00161 ThreadWin32Impl *self = (ThreadWin32Impl *)data;
00162 BOOL result = TlsSetValue(_pt_ptr_index, self->_parent_obj);
00163 nassertr(result, 1);
00164
00165 {
00166 self->_mutex.acquire();
00167 nassertd(self->_status == S_start_called) {
00168 self->_mutex.release();
00169 return 1;
00170 }
00171 self->_status = S_running;
00172 self->_cv.notify();
00173 self->_mutex.release();
00174 }
00175
00176 self->_parent_obj->thread_main();
00177
00178 if (thread_cat->is_debug()) {
00179 thread_cat.debug()
00180 << "Terminating thread " << self->_parent_obj->get_name()
00181 << ", count = " << self->_parent_obj->get_ref_count() << "\n";
00182 }
00183
00184 {
00185 self->_mutex.acquire();
00186 nassertd(self->_status == S_running) {
00187 self->_mutex.release();
00188 return 1;
00189 }
00190 self->_status = S_finished;
00191 self->_cv.notify();
00192 self->_mutex.release();
00193 }
00194
00195
00196
00197
00198 unref_delete(self->_parent_obj);
00199 }
00200
00201 return 0;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 void ThreadWin32Impl::
00211 init_pt_ptr_index() {
00212 nassertv(!_got_pt_ptr_index);
00213
00214 _pt_ptr_index = TlsAlloc();
00215 if (_pt_ptr_index == TLS_OUT_OF_INDEXES) {
00216 thread_cat->error()
00217 << "Unable to associate Thread pointers with threads.\n";
00218 return;
00219 }
00220
00221 _got_pt_ptr_index = true;
00222
00223
00224
00225 Thread *main_thread_obj = Thread::get_main_thread();
00226 BOOL result = TlsSetValue(_pt_ptr_index, main_thread_obj);
00227 nassertv(result);
00228 }
00229
00230 #endif // THREAD_WIN32_IMPL