Panda3D
thread.cxx
1 // Filename: thread.cxx
2 // Created by: drose (08Aug02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "thread.h"
16 #include "mainThread.h"
17 #include "externalThread.h"
18 #include "config_pipeline.h"
19 #include "mutexDebug.h"
20 #include "conditionVarDebug.h"
21 #include "conditionVarFullDebug.h"
22 
23 Thread *Thread::_main_thread;
24 Thread *Thread::_external_thread;
25 TypeHandle Thread::_type_handle;
26 
27 ////////////////////////////////////////////////////////////////////
28 // Function: Thread::Constructor
29 // Access: Protected
30 // Description: Creates a new Thread object, but does not
31 // immediately start executing it. This gives the
32 // caller a chance to store it in a PT(Thread) object,
33 // if desired, before the thread gets a chance to
34 // terminate and destruct itself.
35 //
36 // Call start() to begin thread execution.
37 //
38 // The name should be unique for each thread (though
39 // this is not enforced, and not strictly required).
40 // The sync_name can be shared between multiple
41 // different threads; threads that run synchronously
42 // with each other should be given the same sync_name,
43 // for the benefit of PStats.
44 ////////////////////////////////////////////////////////////////////
45 Thread::
46 Thread(const string &name, const string &sync_name) :
47  Namable(name),
48  _sync_name(sync_name),
49  _impl(this)
50 {
51  _started = false;
52  _pstats_index = -1;
53  _pstats_callback = NULL;
54  _pipeline_stage = 0;
55  _joinable = false;
56  _current_task = NULL;
57 
58 #ifdef HAVE_PYTHON
59  _python_data = Py_None;
60  Py_INCREF(_python_data);
61 #endif
62 
63 #ifdef DEBUG_THREADS
64  _blocked_on_mutex = NULL;
65  _waiting_on_cvar = NULL;
66  _waiting_on_cvar_full = NULL;
67 #endif
68 
69 #if defined(HAVE_PYTHON) && !defined(SIMPLE_THREADS)
70  // Ensure that the Python threading system is initialized and ready
71  // to go.
72 #ifdef WITH_THREAD // This symbol defined within Python.h
73 
74 #if PY_VERSION_HEX >= 0x03020000
75  Py_Initialize();
76 #endif
77 
78  PyEval_InitThreads();
79 #endif
80 #endif
81 }
82 
83 ////////////////////////////////////////////////////////////////////
84 // Function: Thread::Destructor
85 // Access: Published, Virtual
86 // Description:
87 ////////////////////////////////////////////////////////////////////
88 Thread::
89 ~Thread() {
90 #ifdef HAVE_PYTHON
91  Py_DECREF(_python_data);
92 #endif
93 
94 #ifdef DEBUG_THREADS
95  nassertv(_blocked_on_mutex == NULL &&
96  _waiting_on_cvar == NULL &&
97  _waiting_on_cvar_full == NULL);
98 #endif
99 }
100 
101 ////////////////////////////////////////////////////////////////////
102 // Function: Thread::bind_thread
103 // Access: Published, Static
104 // Description: Returns a new Panda Thread object associated with the
105 // current thread (which has been created externally).
106 // This can be used to bind a unique Panda Thread object
107 // with an external thread, such as a new Python thread.
108 //
109 // It is particularly useful to bind a Panda Thread
110 // object to an external thread for the purposes of
111 // PStats monitoring. Without this call, each external
112 // thread will be assigned the same global
113 // ExternalThread object, which means they will all
114 // appear in the same PStats graph.
115 //
116 // It is the caller's responsibility to save the
117 // returned Thread pointer for the lifetime of the
118 // external thread. It is an error for the Thread
119 // pointer to destruct while the external thread is
120 // still in the system.
121 //
122 // It is also an error to call this method from the main
123 // thread, or twice within a given thread, unless it is
124 // given the same name each time (in which case the same
125 // pointer will be returned each time).
126 ////////////////////////////////////////////////////////////////////
127 PT(Thread) Thread::
128 bind_thread(const string &name, const string &sync_name) {
129  Thread *current_thread = get_current_thread();
130  if (current_thread != get_external_thread()) {
131  // This thread already has an associated thread.
132  nassertr(current_thread->get_name() == name &&
133  current_thread->get_sync_name() == sync_name, current_thread);
134  return current_thread;
135  }
136 
137  PT(Thread) thread = new ExternalThread(name, sync_name);
138  ThreadImpl::bind_thread(thread);
139  return thread;
140 }
141 
142 ////////////////////////////////////////////////////////////////////
143 // Function: Thread::set_pipeline_stage
144 // Access: Published
145 // Description: Specifies the Pipeline stage number associated with
146 // this thread. The default stage is 0 if no stage is
147 // specified otherwise.
148 //
149 // This must be a value in the range [0
150 // .. pipeline->get_num_stages() - 1]. It specifies the
151 // values that this thread observes for all pipelined
152 // data. Typically, an application thread will leave
153 // this at 0, but a render thread may set it to 1 or 2
154 // (to operate on the previous frame's data, or the
155 // second previous frame's data).
156 ////////////////////////////////////////////////////////////////////
157 void Thread::
158 set_pipeline_stage(int pipeline_stage) {
159 #ifdef THREADED_PIPELINE
160  _pipeline_stage = pipeline_stage;
161 #else
162  if (pipeline_stage != 0) {
163  pipeline_cat.warning()
164  << "Requested pipeline stage " << pipeline_stage
165  << " but multithreaded render pipelines not enabled in build.\n";
166  }
167  _pipeline_stage = 0;
168 #endif
169 }
170 
171 ////////////////////////////////////////////////////////////////////
172 // Function: Thread::output
173 // Access: Published, Virtual
174 // Description:
175 ////////////////////////////////////////////////////////////////////
176 void Thread::
177 output(ostream &out) const {
178  out << get_type() << " " << get_name();
179 }
180 
181 ////////////////////////////////////////////////////////////////////
182 // Function: Thread::output_blocker
183 // Access: Published
184 // Description: Writes a description of the mutex or condition
185 // variable that this thread is blocked on. Writes
186 // nothing if there is no blocker, or if we are not in
187 // DEBUG_THREADS mode.
188 ////////////////////////////////////////////////////////////////////
189 void Thread::
190 output_blocker(ostream &out) const {
191 #ifdef DEBUG_THREADS
192  if (_blocked_on_mutex != (MutexDebug *)NULL) {
193  _blocked_on_mutex->output_with_holder(out);
194  } else if (_waiting_on_cvar != (ConditionVarDebug *)NULL) {
195  out << *_waiting_on_cvar;
196  } else if (_waiting_on_cvar_full != (ConditionVarFullDebug *)NULL) {
197  out << *_waiting_on_cvar_full;
198  }
199 #endif // DEBUG_THREADS
200 }
201 
202 ////////////////////////////////////////////////////////////////////
203 // Function: Thread::write_status
204 // Access: Published, Static
205 // Description:
206 ////////////////////////////////////////////////////////////////////
207 void Thread::
208 write_status(ostream &out) {
209 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
210  ThreadImpl::write_status(out);
211 #endif
212 }
213 
214 ////////////////////////////////////////////////////////////////////
215 // Function: Thread::start
216 // Access: Public
217 // Description: Starts the thread executing. It is only valid to
218 // call this once.
219 //
220 // The thread will begin executing its thread_main()
221 // function, and will terminate when thread_main()
222 // returns.
223 //
224 // priority is intended as a hint to the relative
225 // importance of this thread. This may be ignored by
226 // the thread implementation.
227 //
228 // joinable should be set true if you intend to call
229 // join() to wait for the thread to terminate, or false
230 // if you don't care and you will never call join().
231 // Note that the reference count on the Thread object is
232 // incremented while the thread itself is running, so if
233 // you just want to fire and forget a thread, you may
234 // pass joinable = false, and never store the Thread
235 // object. It will automatically destruct itself when
236 // it finishes.
237 //
238 // The return value is true if the thread is
239 // successfully started, false otherwise.
240 ////////////////////////////////////////////////////////////////////
241 bool Thread::
242 start(ThreadPriority priority, bool joinable) {
243  nassertr(!_started, false);
244 
245  if (!support_threads) {
246  thread_cat->warning()
247  << *this << " could not be started: support-threads is false.\n";
248  return false;
249  }
250 
251  _joinable = joinable;
252  _started = _impl.start(priority, joinable);
253 
254  if (!_started) {
255  thread_cat->warning()
256  << *this << " could not be started!\n";
257  }
258 
259  return _started;
260 }
261 
262 #ifdef HAVE_PYTHON
263 ////////////////////////////////////////////////////////////////////
264 // Function: Thread::set_python_data
265 // Access: Published
266 // Description: Sets an arbitrary Python object that may be
267 // associated with this thread object. This is just for
268 // the purposes of associated arbitrary Python data with
269 // the C++ object; other than managing the reference
270 // count, the C++ code does nothing with this object.
271 ////////////////////////////////////////////////////////////////////
272 void Thread::
273 set_python_data(PyObject *python_data) {
274  Py_DECREF(_python_data);
275  _python_data = python_data;
276  Py_INCREF(_python_data);
277 }
278 #endif // HAVE_PYTHON
279 
280 #ifdef HAVE_PYTHON
281 ////////////////////////////////////////////////////////////////////
282 // Function: Thread::get_python_data
283 // Access: Published
284 // Description: Returns the Python object that was set with
285 // set_python_data().
286 ////////////////////////////////////////////////////////////////////
287 PyObject *Thread::
288 get_python_data() const {
289  Py_INCREF(_python_data);
290  return _python_data;
291 }
292 #endif // HAVE_PYTHON
293 
294 #ifdef HAVE_PYTHON
295 ////////////////////////////////////////////////////////////////////
296 // Function: Thread::call_python_func
297 // Access: Public
298 // Description: Internal function to safely call a Python function
299 // within a sub-thread, that might execute in parallel
300 // with existing Python code. The return value is the
301 // return value of the Python function, or NULL if there
302 // was an exception.
303 ////////////////////////////////////////////////////////////////////
304 PyObject *Thread::
305 call_python_func(PyObject *function, PyObject *args) {
306  nassertr(this == get_current_thread(), NULL);
307 
308  // Create a new Python thread state data structure, so Python can
309  // properly lock itself.
310  PyObject *result = NULL;
311 
312  if (this == get_main_thread()) {
313  // In the main thread, just call the function.
314  result = PyObject_Call(function, args, NULL);
315 
316  if (result == (PyObject *)NULL) {
317  if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) {
318  // If we caught SystemExit, let it pass by without bothering
319  // to print a callback.
320 
321  } else {
322  // Temporarily save and restore the exception state so we can
323  // print a callback on-the-spot.
324  PyObject *exc, *val, *tb;
325  PyErr_Fetch(&exc, &val, &tb);
326 
327  Py_XINCREF(exc);
328  Py_XINCREF(val);
329  Py_XINCREF(tb);
330  PyErr_Restore(exc, val, tb);
331  PyErr_Print();
332 
333  PyErr_Restore(exc, val, tb);
334  }
335  }
336 
337  } else {
338 #ifndef HAVE_THREADS
339  // Shouldn't be possible to come here without having some kind of
340  // threading support enabled.
341  nassertr(false, NULL);
342 #else
343 
344 #ifdef SIMPLE_THREADS
345  // We can't use the PyGILState interface, which assumes we are
346  // using true OS-level threading. PyGILState enforces policies
347  // like only one thread state per OS-level thread, which is not
348  // true in the case of SIMPLE_THREADS.
349 
350  // For some reason I don't fully understand, I'm getting a crash
351  // when I clean up old PyThreadState objects with
352  // PyThreadState_Delete(). It appears that the thread state is
353  // still referenced somewhere at the time I call delete, and the
354  // crash occurs because I've deleted an active pointer.
355 
356  // Storing these pointers in a vector for permanent recycling
357  // seems to avoid this problem. I wish I understood better what's
358  // going wrong, but I guess this workaround will do.
359  static pvector<PyThreadState *> thread_states;
360 
361  PyThreadState *orig_thread_state = PyThreadState_Get();
362  PyInterpreterState *istate = orig_thread_state->interp;
363  PyThreadState *new_thread_state;
364  if (thread_states.empty()) {
365  new_thread_state = PyThreadState_New(istate);
366  } else {
367  new_thread_state = thread_states.back();
368  thread_states.pop_back();
369  }
370  PyThreadState_Swap(new_thread_state);
371 
372  // Call the user's function.
373  result = PyObject_Call(function, args, NULL);
374  if (result == (PyObject *)NULL && PyErr_Occurred()) {
375  // We got an exception. Move the exception from the current
376  // thread into the main thread, so it can be handled there.
377  PyObject *exc, *val, *tb;
378  PyErr_Fetch(&exc, &val, &tb);
379 
380  thread_cat.error()
381  << "Exception occurred within " << *this << "\n";
382 
383  // Temporarily restore the exception state so we can print a
384  // callback on-the-spot.
385  Py_XINCREF(exc);
386  Py_XINCREF(val);
387  Py_XINCREF(tb);
388  PyErr_Restore(exc, val, tb);
389  PyErr_Print();
390 
391  PyThreadState_Swap(orig_thread_state);
392  thread_states.push_back(new_thread_state);
393  //PyThreadState_Clear(new_thread_state);
394  //PyThreadState_Delete(new_thread_state);
395 
396  PyErr_Restore(exc, val, tb);
397 
398  // Now attempt to force the main thread to the head of the ready
399  // queue, so it can respond to the exception immediately. This
400  // only works if the main thread is not blocked, of course.
402 
403  } else {
404  // No exception. Restore the thread state normally.
405  PyThreadState *state = PyThreadState_Swap(orig_thread_state);
406  thread_states.push_back(new_thread_state);
407  //PyThreadState_Clear(new_thread_state);
408  //PyThreadState_Delete(new_thread_state);
409  }
410 
411 #else // SIMPLE_THREADS
412  // With true threading enabled, we're better off using PyGILState.
413  PyGILState_STATE gstate;
414  gstate = PyGILState_Ensure();
415 
416  // Call the user's function.
417  result = PyObject_Call(function, args, NULL);
418  if (result == (PyObject *)NULL && PyErr_Occurred()) {
419  // We got an exception. Move the exception from the current
420  // thread into the main thread, so it can be handled there.
421  PyObject *exc, *val, *tb;
422  PyErr_Fetch(&exc, &val, &tb);
423 
424  thread_cat.error()
425  << "Exception occurred within " << *this << "\n";
426 
427  // Temporarily restore the exception state so we can print a
428  // callback on-the-spot.
429  Py_XINCREF(exc);
430  Py_XINCREF(val);
431  Py_XINCREF(tb);
432  PyErr_Restore(exc, val, tb);
433  PyErr_Print();
434 
435  PyGILState_Release(gstate);
436 
437  PyErr_Restore(exc, val, tb);
438  } else {
439  // No exception. Restore the thread state normally.
440  PyGILState_Release(gstate);
441  }
442 
443 
444 #endif // SIMPLE_THREADS
445 #endif // HAVE_THREADS
446  }
447 
448  return result;
449 }
450 #endif // HAVE_PYTHON
451 
452 #ifdef HAVE_PYTHON
453 ////////////////////////////////////////////////////////////////////
454 // Function: Thread::handle_python_exception
455 // Access: Public
456 // Description: Called when a Python exception is raised during
457 // processing of a thread. Gets the error string and
458 // passes it back to the calling Python process in a
459 // sensible way.
460 ////////////////////////////////////////////////////////////////////
461 void Thread::
462 handle_python_exception() {
463  /*
464  PyObject *exc, *val, *tb;
465  PyErr_Fetch(&exc, &val, &tb);
466 
467  ostringstream strm;
468  strm << "\n";
469 
470  if (PyObject_HasAttrString(exc, "__name__")) {
471  PyObject *exc_name = PyObject_GetAttrString(exc, "__name__");
472  PyObject *exc_str = PyObject_Str(exc_name);
473  strm << PyString_AsString(exc_str);
474  Py_DECREF(exc_str);
475  Py_DECREF(exc_name);
476  } else {
477  PyObject *exc_str = PyObject_Str(exc);
478  strm << PyString_AsString(exc_str);
479  Py_DECREF(exc_str);
480  }
481  Py_DECREF(exc);
482 
483  if (val != (PyObject *)NULL) {
484  PyObject *val_str = PyObject_Str(val);
485  strm << ": " << PyString_AsString(val_str);
486  Py_DECREF(val_str);
487  Py_DECREF(val);
488  }
489  if (tb != (PyObject *)NULL) {
490  Py_DECREF(tb);
491  }
492 
493  strm << "\nException occurred within thread " << get_name();
494  string message = strm.str();
495  nout << message << "\n";
496 
497  nassert_raise(message);
498  */
499 
500  thread_cat.error()
501  << "Exception occurred within " << *this << "\n";
502 
503  // Now attempt to force the main thread to the head of the ready
504  // queue, so it will be the one to receive the above assertion.
505  // This mainly only has an effect if SIMPLE_THREADS is in use.
507 }
508 #endif // HAVE_PYTHON
509 
510 ////////////////////////////////////////////////////////////////////
511 // Function: Thread::init_main_thread
512 // Access: Private, Static
513 // Description: Creates the Thread object that represents the main
514 // thread.
515 ////////////////////////////////////////////////////////////////////
516 void Thread::
517 init_main_thread() {
518  // There is a chance of mutual recursion at startup. The count
519  // variable here attempts to protect against that.
520  static int count = 0;
521  ++count;
522  if (count == 1 && _main_thread == (Thread *)NULL) {
523  _main_thread = new MainThread;
524  _main_thread->ref();
525  }
526 }
527 
528 ////////////////////////////////////////////////////////////////////
529 // Function: Thread::init_external_thread
530 // Access: Private, Static
531 // Description: Creates the Thread object that represents all of the
532 // external threads.
533 ////////////////////////////////////////////////////////////////////
534 void Thread::
535 init_external_thread() {
536  if (_external_thread == (Thread *)NULL) {
537  _external_thread = new ExternalThread;
538  _external_thread->ref();
539  }
540 }
541 
542 ////////////////////////////////////////////////////////////////////
543 // Function: Thread::PStatsCallback::Destructor
544 // Access: Public, Virtual
545 // Description: Since this class is just an interface definition,
546 // there is no need to have a destructor. However, we
547 // must have one anyway to stop gcc's annoying warning.
548 ////////////////////////////////////////////////////////////////////
551 }
552 
553 ////////////////////////////////////////////////////////////////////
554 // Function: Thread::PStatsCallback::deactivate_hook
555 // Access: Public, Virtual
556 // Description: Called when the thread is deactivated (swapped for
557 // another running thread). This is intended to provide
558 // a callback hook for PStats to assign time to
559 // individual threads properly, particularly in the
560 // SIMPLE_THREADS case.
561 ////////////////////////////////////////////////////////////////////
564 }
565 
566 ////////////////////////////////////////////////////////////////////
567 // Function: Thread::PStatsCallback::activate_hook
568 // Access: Public, Virtual
569 // Description: Called when the thread is activated (resumes
570 // execution). This is intended to provide a callback
571 // hook for PStats to assign time to individual threads
572 // properly, particularly in the SIMPLE_THREADS case.
573 ////////////////////////////////////////////////////////////////////
576 }
virtual ~PStatsCallback()
Since this class is just an interface definition, there is no need to have a destructor.
Definition: thread.cxx:550
static Thread * get_external_thread()
Returns a pointer to the "external" Thread object–this is a special Thread object that corresponds t...
Definition: thread.I:124
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
void preempt()
Indicates that this thread should run as soon as possible, preemptying any other threads that may be ...
Definition: thread.I:315
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
static Thread * get_main_thread()
Returns a pointer to the "main" Thread object–this is the Thread that started the whole process...
Definition: thread.I:107
const string & get_sync_name() const
Returns the sync name of the thread.
Definition: thread.I:47
virtual void activate_hook(Thread *thread)
Called when the thread is activated (resumes execution).
Definition: thread.cxx:575
void set_pipeline_stage(int pipeline_stage)
Specifies the Pipeline stage number associated with this thread.
Definition: thread.cxx:158
The special "external thread" class.
A base class for all things which can have a name.
Definition: namable.h:29
void output_blocker(ostream &out) const
Writes a description of the mutex or condition variable that this thread is blocked on...
Definition: thread.cxx:190
The special "main thread" class.
Definition: mainThread.h:27
void ref() const
Explicitly increments the reference count.
A thread; that is, a lightweight process.
Definition: thread.h:51
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
virtual void deactivate_hook(Thread *thread)
Called when the thread is deactivated (swapped for another running thread).
Definition: thread.cxx:563
bool start(ThreadPriority priority, bool joinable)
Starts the thread executing.
Definition: thread.cxx:242