Panda3D
pythonThread.cxx
1 // Filename: pythonThread.cxx
2 // Created by: drose (13Apr07)
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 "pythonThread.h"
16 #include "pnotify.h"
17 
18 #ifdef HAVE_PYTHON
19 
20 TypeHandle PythonThread::_type_handle;
21 
22 ////////////////////////////////////////////////////////////////////
23 // Function: PythonThread::Constructor
24 // Access: Published
25 // Description:
26 ////////////////////////////////////////////////////////////////////
27 PythonThread::
28 PythonThread(PyObject *function, PyObject *args,
29  const string &name, const string &sync_name) :
30  Thread(name, sync_name)
31 {
32  _function = function;
33  Py_INCREF(_function);
34  _args = NULL;
35  _result = NULL;
36 
37  if (!PyCallable_Check(_function)) {
38  nassert_raise("Invalid function passed to PythonThread constructor");
39  }
40 
41  if (args == Py_None) {
42  // None means no arguments; create an empty tuple.
43  _args = PyTuple_New(0);
44  } else {
45  _args = NULL;
46  if (PySequence_Check(args)) {
47  _args = PySequence_Tuple(args);
48  }
49  if (_args == NULL) {
50  nassert_raise("Invalid args passed to PythonThread constructor");
51  }
52  }
53 
54 #ifndef SIMPLE_THREADS
55  // Ensure that the Python threading system is initialized and ready to go.
56 #ifdef WITH_THREAD // This symbol defined within Python.h
57  PyEval_InitThreads();
58 #endif
59 #endif
60 }
61 
62 ////////////////////////////////////////////////////////////////////
63 // Function: PythonThread::Destructor
64 // Access: Published, Virtual
65 // Description:
66 ////////////////////////////////////////////////////////////////////
67 PythonThread::
68 ~PythonThread() {
69  // Unfortunately, we need to grab the GIL to release these things,
70  // since the destructor could be called from any thread.
71 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
72  PyGILState_STATE gstate;
73  gstate = PyGILState_Ensure();
74 #endif
75 
76  Py_DECREF(_function);
77  Py_XDECREF(_args);
78  Py_XDECREF(_result);
79 
80 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
81  PyGILState_Release(gstate);
82 #endif
83 }
84 
85 ////////////////////////////////////////////////////////////////////
86 // Function: PythonThread::join
87 // Access: Published
88 // Description: Blocks the calling process until the thread
89 // terminates. If the thread has already terminated,
90 // this returns immediately.
91 //
92 // The PythonThread flavor of this function returns the
93 // same value returned by the thread function.
94 ////////////////////////////////////////////////////////////////////
95 PyObject *PythonThread::
96 join() {
97  Thread::join();
98 
99  if (_result == NULL) {
100  // No result; return None.
101  return Py_BuildValue("");
102  }
103 
104  Py_INCREF(_result);
105  return _result;
106 }
107 
108 ////////////////////////////////////////////////////////////////////
109 // Function: PythonThread::thread_main
110 // Access: Protected, Virtual
111 // Description:
112 ////////////////////////////////////////////////////////////////////
113 void PythonThread::
114 thread_main() {
115  _result = call_python_func(_function, _args);
116 }
117 
118 #endif // HAVE_PYTHON
void join()
Blocks the calling process until the thread terminates.
Definition: thread.I:298
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