Panda3D
|
00001 // Filename: threadSimpleImpl.cxx 00002 // Created by: drose (18Jun07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 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 // Function: ThreadSimpleImpl::Constructor 00029 // Access: Public 00030 // Description: 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 // Save this pointer for convenience. 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 // Function: ThreadSimpleImpl::Destructor 00065 // Access: Public 00066 // Description: 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 // Function: ThreadSimpleImpl::setup_main_thread 00086 // Access: Public 00087 // Description: Called for the main thread only, which has been 00088 // already started, to fill in the values appropriate to 00089 // that thread. 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 // Function: ThreadSimpleImpl::start 00109 // Access: Public 00110 // Description: 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 // We'll keep the reference count upped while the thread is running. 00149 // When the thread finishes, we'll drop the reference count. 00150 _parent_obj->ref(); 00151 00152 #ifdef HAVE_PYTHON 00153 // Query the current Python thread state. 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 // Function: ThreadSimpleImpl::join 00166 // Access: Public 00167 // Description: Blocks the calling process until the thread 00168 // terminates. If the thread has already terminated, 00169 // this returns immediately. 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 // Function: ThreadSimpleImpl::preempt 00185 // Access: Public 00186 // Description: 00187 //////////////////////////////////////////////////////////////////// 00188 void ThreadSimpleImpl:: 00189 preempt() { 00190 _manager->preempt(this); 00191 } 00192 00193 //////////////////////////////////////////////////////////////////// 00194 // Function: ThreadSimpleImpl::get_unique_id 00195 // Access: Public 00196 // Description: 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 // Function: ThreadSimpleImpl::prepare_for_exit 00213 // Access: Public, Static 00214 // Description: Waits for all threads to terminate. Normally this is 00215 // called only from the main thread. 00216 //////////////////////////////////////////////////////////////////// 00217 void ThreadSimpleImpl:: 00218 prepare_for_exit() { 00219 ThreadSimpleManager *manager = ThreadSimpleManager::get_global_ptr(); 00220 manager->prepare_for_exit(); 00221 } 00222 00223 //////////////////////////////////////////////////////////////////// 00224 // Function: ThreadSimpleImpl::sleep_this 00225 // Access: Public 00226 // Description: 00227 //////////////////////////////////////////////////////////////////// 00228 void ThreadSimpleImpl:: 00229 sleep_this(double seconds) { 00230 _manager->enqueue_sleep(this, seconds); 00231 _manager->next_context(); 00232 } 00233 00234 //////////////////////////////////////////////////////////////////// 00235 // Function: ThreadSimpleImpl::yield_this 00236 // Access: Public 00237 // Description: 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 // Function: ThreadSimpleImpl::st_begin_thread 00251 // Access: Private, Static 00252 // Description: This method is called as the first introduction to a 00253 // new thread. 00254 //////////////////////////////////////////////////////////////////// 00255 void ThreadSimpleImpl:: 00256 st_begin_thread(void *data) { 00257 ThreadSimpleImpl *self = (ThreadSimpleImpl *)data; 00258 self->begin_thread(); 00259 } 00260 00261 //////////////////////////////////////////////////////////////////// 00262 // Function: ThreadSimpleImpl::begin_thread 00263 // Access: Private 00264 // Description: This method is called as the first introduction to a 00265 // new thread. 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 // Here we are executing within the thread. Run the thread_main 00281 // function defined for this thread. 00282 _parent_obj->thread_main(); 00283 00284 // Now we have completed the thread. 00285 _status = TS_finished; 00286 00287 // Any threads that were waiting to join with this thread now become ready. 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 // Shouldn't get here. 00298 nassertv(false); 00299 abort(); 00300 } 00301 00302 #endif // THREAD_SIMPLE_IMPL