From b660d0f3e5e4c70e241c9df17501c4053c25f1fc Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 9 Jun 2009 20:30:24 +0000 Subject: [PATCH] p3dpython can be a Panda app --- direct/src/plugin/Sources.pp | 13 +++-- direct/src/plugin/p3dCInstance.h | 8 +-- direct/src/plugin/p3dPythonRun.cxx | 80 ++++++++++-------------------- direct/src/plugin/p3dPythonRun.h | 37 ++++++++------ 4 files changed, 63 insertions(+), 75 deletions(-) diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index 06f7378a83..871a783c14 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -1,6 +1,6 @@ // This directory is still experimental. Define HAVE_P3D_PLUGIN in // your Config.pp to build it. -#define BUILD_DIRECTORY $[HAVE_P3D_PLUGIN] +#define BUILD_DIRECTORY $[and $[HAVE_P3D_PLUGIN],$[HAVE_PYTHON],$[HAVE_TINYXML]] #begin lib_target #define USE_PACKAGES tinyxml @@ -30,13 +30,20 @@ #end lib_target #begin bin_target - #define USE_PACKAGES tinyxml + #define USE_PACKAGES tinyxml python #define TARGET p3dpython +#define OTHER_LIBS \ + dtoolutil:c dtoolbase:c dtool:m \ + interrogatedb:c dconfig:c dtoolconfig:m \ + express:c pandaexpress:m \ + prc:c pstatclient:c pandabase:c linmath:c putil:c \ + pipeline:c panda:m + #define SOURCES \ handleStream.cxx handleStream.h handleStream.I \ handleStreamBuf.cxx handleStreamBuf.h \ - p3d_lock.h \ + p3d_lock.h p3d_plugin.h \ p3dCInstance.cxx \ p3dCInstance.h p3dCInstance.I \ p3dPythonRun.cxx p3dPythonRun.h p3dPythonRun.I diff --git a/direct/src/plugin/p3dCInstance.h b/direct/src/plugin/p3dCInstance.h index 9e7968a2aa..ebfaa4fbeb 100755 --- a/direct/src/plugin/p3dCInstance.h +++ b/direct/src/plugin/p3dCInstance.h @@ -15,9 +15,11 @@ #ifndef P3DCINSTANCE_H #define P3DCINSTANCE_H -#include "p3d_plugin.h" +#include "pandabase.h" + +#include "p3d_plugin.h" +#include "pvector.h" -#include #include class P3DSession; @@ -41,7 +43,7 @@ private: string _keyword; string _value; }; - typedef vector Tokens; + typedef pvector Tokens; P3D_request_ready_func *_func; string _p3d_filename; diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 9185996a51..883fe6865d 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -13,6 +13,7 @@ //////////////////////////////////////////////////////////////////// #include "p3dPythonRun.h" +#include "asyncTaskManager.h" //////////////////////////////////////////////////////////////////// // Function: P3DPythonRun::Constructor @@ -114,41 +115,10 @@ run_python() { } Py_DECREF(appmf); - // Construct a Python wrapper around our check_comm() method. - - static PyMethodDef p3dpython_methods[] = { - {"check_comm", P3DPythonRun::py_check_comm, METH_VARARGS, - "Check for communications to and from the plugin host."}, - {NULL, NULL, 0, NULL} /* Sentinel */ - }; - PyObject *p3dpython = Py_InitModule("p3dpython", p3dpython_methods); - if (p3dpython == NULL) { - PyErr_Print(); - return false; - } - - PyObject *check_comm = PyObject_GetAttrString(p3dpython, "check_comm"); - if (check_comm == NULL) { - PyErr_Print(); - return false; - } - - // Now add check_comm() as a Python task. - PyObject *add_check_comm = PyObject_GetAttrString(appmf, "add_check_comm"); - if (add_check_comm == NULL) { - PyErr_Print(); - return false; - } - - PyObject *task = PyObject_CallFunction - (add_check_comm, "Ol", check_comm, (long)this); - if (task == NULL) { - PyErr_Print(); - return false; - } - Py_DECREF(task); - Py_DECREF(add_check_comm); - Py_DECREF(check_comm); + // Now add check_comm() as a task. + _check_comm_task = new GenericAsyncTask("check_comm", st_check_comm, this); + AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr(); + task_mgr->add(_check_comm_task); // Finally, get lost in taskMgr.run(). @@ -212,8 +182,8 @@ handle_command(TiXmlDocument *doc) { // from, and requests to be delivered to, the plugin // host in the parent process. //////////////////////////////////////////////////////////////////// -void P3DPythonRun:: -check_comm() { +AsyncTask::DoneStatus P3DPythonRun:: +check_comm(GenericAsyncTask *task) { ACQUIRE_LOCK(_commands_lock); while (!_commands.empty()) { TiXmlDocument *doc = _commands.front(); @@ -232,27 +202,21 @@ check_comm() { } RELEASE_LOCK(_commands_lock); + + return AsyncTask::DS_cont; } //////////////////////////////////////////////////////////////////// -// Function: P3DPythonRun::py_check_comm +// Function: P3DPythonRun::st_check_comm // Access: Private, Static -// Description: This method is added as a Python task function on the -// task manager. It is the Python wrapper around the -// check_comm method. +// Description: This static function wrapper around check_comm is +// necessary to add the method function to the +// GenericAsyncTask object. //////////////////////////////////////////////////////////////////// -PyObject *P3DPythonRun:: -py_check_comm(PyObject *, PyObject *args) { - long this_int; - PyObject *task; - if (!PyArg_ParseTuple(args, "lO:check_comm", &this_int, &task)) { - return NULL; - } - - P3DPythonRun *self = (P3DPythonRun *)(void *)this_int; - self->check_comm(); - - return PyObject_GetAttrString(task, "cont"); +AsyncTask::DoneStatus P3DPythonRun:: +st_check_comm(GenericAsyncTask *task, void *user_data) { + P3DPythonRun *self = (P3DPythonRun *)user_data; + return self->check_comm(task); } //////////////////////////////////////////////////////////////////// @@ -266,6 +230,12 @@ void P3DPythonRun:: spawn_read_thread() { assert(!_read_thread_continue); + // We have to use direct OS calls to create the thread instead of + // Panda constructs, because it has to be an actual thread, not + // necessarily a Panda thread (we can't use Panda's simple threads + // implementation, because we can't get overlapped I/O on an + // anonymous pipe in Windows). + _read_thread_continue = true; #ifdef _WIN32 _read_thread = CreateThread(NULL, 0, &win_rt_thread_run, this, 0, NULL); @@ -356,8 +326,8 @@ terminate_instance(int id) { delete inst; // TODO: we don't currently have any way to stop just one instance - // of a multi-instance session. We could maybe close its window or - // something. + // of a multi-instance session. This will require a different + // Python interface than ShowBase. terminate_session(); } diff --git a/direct/src/plugin/p3dPythonRun.h b/direct/src/plugin/p3dPythonRun.h index fa2cd06291..68f2b9d8a5 100755 --- a/direct/src/plugin/p3dPythonRun.h +++ b/direct/src/plugin/p3dPythonRun.h @@ -15,20 +15,22 @@ #ifndef P3DPYTHONRUN_H #define P3DPYTHONRUN_H -#include -#include -#include -#include -#include -#include -#include +#include "pandabase.h" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + #include "p3d_lock.h" #include "handleStream.h" #include "p3dCInstance.h" +#include "genericAsyncTask.h" +#include "pmap.h" +#include "pdeque.h" -#ifdef _WIN32 -#include -#endif +#include +#include using namespace std; @@ -56,8 +58,8 @@ public: private: void handle_command(TiXmlDocument *doc); - void check_comm(); - static PyObject *py_check_comm(PyObject *, PyObject *args); + AsyncTask::DoneStatus check_comm(GenericAsyncTask *task); + static AsyncTask::DoneStatus st_check_comm(GenericAsyncTask *task, void *user_data); void spawn_read_thread(); void join_read_thread(); @@ -68,13 +70,14 @@ private: private: // This method runs only within the read thread. + void rt_thread_run(); #ifdef _WIN32 static DWORD WINAPI win_rt_thread_run(LPVOID data); #endif private: - typedef map Instances; + typedef pmap Instances; Instances _instances; string _program_name; @@ -85,9 +88,15 @@ private: PyObject *_exit; PyObject *_setupWindow; + PT(GenericAsyncTask) _check_comm_task; + // The remaining members are manipulated by the read thread. - typedef deque Commands; + typedef pdeque Commands; Commands _commands; + + // This has to be an actual OS LOCK instead of Panda's Mutex, + // because we have to use a true thread here, not one of Panda's + // simple threads. LOCK _commands_lock; HandleStream _pipe_read;