00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "selectThreadImpl.h"
00016
00017 #ifdef THREAD_SIMPLE_IMPL
00018
00019 #include "threadSimpleImpl.h"
00020 #include "threadSimpleManager.h"
00021 #include "thread.h"
00022
00023 ThreadSimpleImpl *volatile ThreadSimpleImpl::_st_this;
00024
00025 int ThreadSimpleImpl::_next_unique_id = 1;
00026
00027
00028
00029
00030
00031
00032 ThreadSimpleImpl::
00033 ThreadSimpleImpl(Thread *parent_obj) :
00034 _parent_obj(parent_obj)
00035 {
00036 _unique_id = _next_unique_id;
00037 ++_next_unique_id;
00038
00039 _status = TS_new;
00040 _joinable = false;
00041 _priority = TP_normal;
00042 _priority_weight = 1.0;
00043 _run_ticks = 0;
00044 _start_time = 0.0;
00045 _stop_time = 0.0;
00046 _wake_time = 0.0;
00047
00048 _context = alloc_thread_context();
00049 _stack = NULL;
00050 _stack_size = 0;
00051
00052
00053 _manager = ThreadSimpleManager::get_global_ptr();
00054
00055 #ifdef HAVE_POSIX_THREADS
00056 _posix_system_thread_id = (pthread_t)-1;
00057 #endif
00058 #ifdef WIN32
00059 _win32_system_thread_id = 0;
00060 #endif
00061 }
00062
00063
00064
00065
00066
00067
00068 ThreadSimpleImpl::
00069 ~ThreadSimpleImpl() {
00070 if (thread_cat->is_debug()) {
00071 thread_cat.debug()
00072 << "Deleting thread " << _parent_obj->get_name() << "\n";
00073 }
00074 nassertv(_status != TS_running);
00075
00076 free_thread_context(_context);
00077
00078 if (_stack != (void *)NULL) {
00079 memory_hook->mmap_free(_stack, _stack_size);
00080 }
00081 _manager->remove_thread(this);
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091 void ThreadSimpleImpl::
00092 setup_main_thread() {
00093 _status = TS_running;
00094 _priority = TP_normal;
00095 _priority_weight = _manager->_simple_thread_normal_weight;
00096
00097 #ifdef HAVE_POSIX_THREADS
00098 _posix_system_thread_id = pthread_self();
00099 #endif
00100 #ifdef WIN32
00101 _win32_system_thread_id = GetCurrentThreadId();
00102 #endif
00103
00104 _manager->set_current_thread(this);
00105 }
00106
00107
00108
00109
00110
00111
00112 bool ThreadSimpleImpl::
00113 start(ThreadPriority priority, bool joinable) {
00114 if (thread_cat->is_debug()) {
00115 thread_cat.debug() << "Starting " << *_parent_obj << "\n";
00116 }
00117
00118 nassertr(_status == TS_new, false);
00119
00120 nassertr(_stack == NULL, false);
00121 _stack_size = memory_hook->round_up_to_page_size((size_t)thread_stack_size);
00122 if (needs_stack_prealloc) {
00123 _stack = (unsigned char *)memory_hook->mmap_alloc(_stack_size, true);
00124 }
00125
00126 _joinable = joinable;
00127 _status = TS_running;
00128 _priority = priority;
00129
00130 switch (priority) {
00131 case TP_low:
00132 _priority_weight = _manager->_simple_thread_low_weight;
00133 break;
00134
00135 case TP_normal:
00136 _priority_weight = _manager->_simple_thread_normal_weight;
00137 break;
00138
00139 case TP_high:
00140 _priority_weight = _manager->_simple_thread_high_weight;
00141 break;
00142
00143 case TP_urgent:
00144 _priority_weight = _manager->_simple_thread_urgent_weight;
00145 break;
00146 }
00147
00148
00149
00150 _parent_obj->ref();
00151
00152 #ifdef HAVE_PYTHON
00153
00154 _python_state = PyThreadState_Swap(NULL);
00155 PyThreadState_Swap(_python_state);
00156 #endif // HAVE_PYTHON
00157
00158 init_thread_context(_context, _stack, _stack_size, st_begin_thread, this);
00159
00160 _manager->enqueue_ready(this, false);
00161 return true;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 void ThreadSimpleImpl::
00172 join() {
00173 nassertv(_joinable);
00174 if (_status == TS_running) {
00175 ThreadSimpleImpl *thread = _manager->get_current_thread();
00176 if (thread != this) {
00177 _joining_threads.push_back(thread);
00178 _manager->next_context();
00179 }
00180 }
00181 }
00182
00183
00184
00185
00186
00187
00188 void ThreadSimpleImpl::
00189 preempt() {
00190 _manager->preempt(this);
00191 }
00192
00193
00194
00195
00196
00197
00198 string ThreadSimpleImpl::
00199 get_unique_id() const {
00200 ostringstream strm;
00201 #ifdef WIN32
00202 strm << GetCurrentProcessId();
00203 #else
00204 strm << getpid();
00205 #endif
00206 strm << "." << _unique_id;
00207
00208 return strm.str();
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 void ThreadSimpleImpl::
00218 prepare_for_exit() {
00219 ThreadSimpleManager *manager = ThreadSimpleManager::get_global_ptr();
00220 manager->prepare_for_exit();
00221 }
00222
00223
00224
00225
00226
00227
00228 void ThreadSimpleImpl::
00229 sleep_this(double seconds) {
00230 _manager->enqueue_sleep(this, seconds);
00231 _manager->next_context();
00232 }
00233
00234
00235
00236
00237
00238
00239 void ThreadSimpleImpl::
00240 yield_this(bool volunteer) {
00241 if (thread_cat->is_debug() && volunteer) {
00242 thread_cat.debug()
00243 << "Force-yielding " << _parent_obj->get_name() << "\n";
00244 }
00245 _manager->enqueue_ready(this, true);
00246 _manager->next_context();
00247 }
00248
00249
00250
00251
00252
00253
00254
00255 void ThreadSimpleImpl::
00256 st_begin_thread(void *data) {
00257 ThreadSimpleImpl *self = (ThreadSimpleImpl *)data;
00258 self->begin_thread();
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 void ThreadSimpleImpl::
00268 begin_thread() {
00269 #ifdef HAVE_PYTHON
00270 PyThreadState_Swap(_python_state);
00271 #endif // HAVE_PYTHON
00272
00273 #ifdef HAVE_POSIX_THREADS
00274 _posix_system_thread_id = pthread_self();
00275 #endif
00276 #ifdef WIN32
00277 _win32_system_thread_id = GetCurrentThreadId();
00278 #endif
00279
00280
00281
00282 _parent_obj->thread_main();
00283
00284
00285 _status = TS_finished;
00286
00287
00288 JoiningThreads::iterator jti;
00289 for (jti = _joining_threads.begin(); jti != _joining_threads.end(); ++jti) {
00290 _manager->enqueue_ready(*jti, false);
00291 }
00292 _joining_threads.clear();
00293
00294 _manager->enqueue_finished(this);
00295 _manager->next_context();
00296
00297
00298 nassertv(false);
00299 abort();
00300 }
00301
00302 #endif // THREAD_SIMPLE_IMPL