26PythonThread(PyObject *function, PyObject *args,
27 const std::string &name,
const std::string &sync_name) :
35 if (!PyCallable_Check(_function)) {
36 nassert_raise(
"Invalid function passed to PythonThread constructor");
41#if !defined(SIMPLE_THREADS) && defined(WITH_THREAD) && PY_VERSION_HEX < 0x03090000
56#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
57 PyGILState_STATE gstate;
58 gstate = PyGILState_Ensure();
65#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
66 PyGILState_Release(gstate);
77PyObject *PythonThread::
81 if (_result ==
nullptr) {
94PyObject *PythonThread::
103set_args(PyObject *args) {
106 if (args == Py_None) {
108 _args = PyTuple_New(0);
111 if (PySequence_Check(args)) {
112 _args = PySequence_Tuple(args);
114 if (_args ==
nullptr) {
115 Dtool_Raise_TypeError(
"PythonThread args must be a tuple");
127PyObject *PythonThread::
128call_python_func(PyObject *function, PyObject *args) {
129 Thread *current_thread = get_current_thread();
133 PyObject *result =
nullptr;
135 if (current_thread == get_main_thread()) {
137 result = PyObject_Call(function, args,
nullptr);
139 if (result ==
nullptr) {
140 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) {
147 PyObject *exc, *val, *tb;
148 PyErr_Fetch(&exc, &val, &tb);
153 PyErr_Restore(exc, val, tb);
156 PyErr_Restore(exc, val, tb);
164 nassert_raise(
"threading support disabled");
185 PyThreadState *orig_thread_state = PyThreadState_Get();
186 PyInterpreterState *istate = orig_thread_state->interp;
187 PyThreadState *new_thread_state;
188 if (thread_states.empty()) {
189 new_thread_state = PyThreadState_New(istate);
191 new_thread_state = thread_states.back();
192 thread_states.pop_back();
194 PyThreadState_Swap(new_thread_state);
197 result = PyObject_Call(function, args,
nullptr);
198 if (result ==
nullptr && PyErr_Occurred()) {
201 PyObject *exc, *val, *tb;
202 PyErr_Fetch(&exc, &val, &tb);
205 <<
"Exception occurred within " << *current_thread <<
"\n";
212 PyErr_Restore(exc, val, tb);
215 PyThreadState_Swap(orig_thread_state);
216 thread_states.push_back(new_thread_state);
220 PyErr_Restore(exc, val, tb);
229 PyThreadState_Swap(orig_thread_state);
230 thread_states.push_back(new_thread_state);
237 PyGILState_STATE gstate;
238 gstate = PyGILState_Ensure();
241 result = PyObject_Call(function, args,
nullptr);
242 if (result ==
nullptr && PyErr_Occurred()) {
245 PyObject *exc, *val, *tb;
246 PyErr_Fetch(&exc, &val, &tb);
249 <<
"Exception occurred within " << *current_thread <<
"\n";
256 PyErr_Restore(exc, val, tb);
259 PyGILState_Release(gstate);
261 if (PyGILState_Check()) {
262 PyErr_Restore(exc, val, tb);
266 PyGILState_Release(gstate);
283 _result = call_python_func(_function, _args);
A thread; that is, a lightweight process.
void join()
Blocks the calling process until the thread terminates.
get_main_thread
Returns a pointer to the "main" Thread object–this is the Thread that started the whole process.
TypeHandle is the identifier used to differentiate C++ class types.
This is our own Panda specialization on the default STL vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.