mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
command-and-response
This commit is contained in:
parent
774ba59dc9
commit
891051485d
@ -21,6 +21,7 @@
|
||||
p3d_plugin_config.h \
|
||||
p3d_plugin_common.h \
|
||||
p3dBoolObject.h \
|
||||
p3dConditionVar.h p3dConditionVar.I \
|
||||
p3dDownload.h p3dDownload.I \
|
||||
p3dFileDownload.h p3dFileDownload.I \
|
||||
p3dFileParams.h p3dFileParams.I \
|
||||
@ -41,6 +42,7 @@
|
||||
#define INCLUDED_SOURCES \
|
||||
p3d_plugin.cxx \
|
||||
p3dBoolObject.cxx \
|
||||
p3dConditionVar.cxx \
|
||||
p3dDownload.cxx \
|
||||
p3dFileDownload.cxx \
|
||||
p3dFileParams.cxx \
|
||||
|
14
direct/src/plugin/p3dConditionVar.I
Normal file
14
direct/src/plugin/p3dConditionVar.I
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: p3dConditionVar.I
|
||||
// Created by: drose (02Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
136
direct/src/plugin/p3dConditionVar.cxx
Normal file
136
direct/src/plugin/p3dConditionVar.cxx
Normal file
@ -0,0 +1,136 @@
|
||||
// Filename: p3dConditionVar.cxx
|
||||
// Created by: drose (02Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "p3dConditionVar.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DConditionVar::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DConditionVar::
|
||||
P3DConditionVar() {
|
||||
#ifdef _WIN32
|
||||
InitializeCriticalSection(&_lock);
|
||||
|
||||
// Create an auto-reset event.
|
||||
_event_signal = CreateEvent(NULL, false, false, NULL);
|
||||
|
||||
#else // _WIN32
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
|
||||
int result = pthread_mutex_init(&_lock, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
assert(result == 0);
|
||||
|
||||
result = pthread_cond_init(&_cvar, NULL);
|
||||
assert(result == 0);
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DConditionVar::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DConditionVar::
|
||||
~P3DConditionVar() {
|
||||
#ifdef _WIN32
|
||||
DeleteCriticalSection(&_lock);
|
||||
CloseHandle(_event_signal);
|
||||
|
||||
#else // _WIN32
|
||||
int result = pthread_mutex_destroy(&_lock);
|
||||
assert(result == 0);
|
||||
|
||||
result = pthread_cond_destroy(&_cvar);
|
||||
assert(result == 0);
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DConditionVar::acquire
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DConditionVar::
|
||||
acquire() {
|
||||
#ifdef _WIN32
|
||||
EnterCriticalSection(&_lock);
|
||||
|
||||
#else // _WIN32
|
||||
int result = pthread_mutex_lock(&_lock);
|
||||
assert(result == 0);
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DConditionVar::wait
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DConditionVar::
|
||||
wait() {
|
||||
#ifdef _WIN32
|
||||
LeaveCriticalSection(&_lock);
|
||||
|
||||
DWORD result = WaitForSingleObject(_event_signal, INFINITE);
|
||||
assert(result == WAIT_OBJECT_0);
|
||||
|
||||
EnterCriticalSection(&_lock);
|
||||
|
||||
#else // _WIN32
|
||||
int result = pthread_cond_wait(&_cvar, &_mutex._lock);
|
||||
assert(result == 0);
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DConditionVar::notify
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DConditionVar::
|
||||
notify() {
|
||||
#ifdef _WIN32
|
||||
SetEvent(_event_signal);
|
||||
|
||||
#else // _WIN32
|
||||
int result = pthread_cond_signal(&_cvar);
|
||||
assert(result == 0);
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DConditionVar::release
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DConditionVar::
|
||||
release() {
|
||||
#ifdef _WIN32
|
||||
LeaveCriticalSection(&_lock);
|
||||
|
||||
#else // _WIN32
|
||||
int result = pthread_mutex_unlock(&_lock);
|
||||
assert(result == 0);
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
49
direct/src/plugin/p3dConditionVar.h
Normal file
49
direct/src/plugin/p3dConditionVar.h
Normal file
@ -0,0 +1,49 @@
|
||||
// Filename: p3dConditionVar.h
|
||||
// Created by: drose (02Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef P3DCONDITIONVAR_H
|
||||
#define P3DCONDITIONVAR_H
|
||||
|
||||
#include "p3d_plugin_common.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DConditionVar
|
||||
// Description : A simple condition-variable like object. It doesn't
|
||||
// support the full condition-var semantics, but it
|
||||
// works well enough with one waiter and one signaller.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class P3DConditionVar {
|
||||
public:
|
||||
P3DConditionVar();
|
||||
~P3DConditionVar();
|
||||
|
||||
void acquire();
|
||||
void wait();
|
||||
void notify();
|
||||
void release();
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
CRITICAL_SECTION _lock;
|
||||
HANDLE _event_signal;
|
||||
|
||||
#else // _WIN32
|
||||
pthread_mutex_t _lock;
|
||||
pthread_cond_t _cvar;
|
||||
#endif // _WIN32
|
||||
};
|
||||
|
||||
#include "p3dConditionVar.I"
|
||||
|
||||
#endif
|
@ -345,38 +345,6 @@ feed_url_stream(int unique_id,
|
||||
return download_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::feed_value
|
||||
// Access: Public
|
||||
// Description: Called by the host in response to a get_property or
|
||||
// call request. The value object must have been
|
||||
// freshly allocated; it will be deleted by this method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
feed_value(int unique_id, P3DObject *value) {
|
||||
if (_session != NULL) {
|
||||
TiXmlDocument *doc = new TiXmlDocument;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xcommand = new TiXmlElement("command");
|
||||
xcommand->SetAttribute("cmd", "feed_value");
|
||||
xcommand->SetAttribute("instance_id", get_instance_id());
|
||||
xcommand->SetAttribute("unique_id", unique_id);
|
||||
if (value != NULL) {
|
||||
TiXmlElement *xvalue = value->make_xml();
|
||||
xcommand->LinkEndChild(xvalue);
|
||||
}
|
||||
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
|
||||
_session->send_command(doc);
|
||||
}
|
||||
|
||||
if (value != NULL) {
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::add_package
|
||||
// Access: Public
|
||||
|
@ -63,7 +63,6 @@ public:
|
||||
size_t total_expected_data,
|
||||
const unsigned char *this_data,
|
||||
size_t this_data_size);
|
||||
void feed_value(int unique_id, P3DObject *value);
|
||||
|
||||
inline int get_instance_id() const;
|
||||
inline const string &get_session_key() const;
|
||||
|
@ -38,14 +38,6 @@ P3DInstanceManager() {
|
||||
_is_initialized = false;
|
||||
_unique_session_index = 0;
|
||||
|
||||
_request_seq = 0;
|
||||
#ifdef _WIN32
|
||||
_request_ready = CreateEvent(NULL, false, false, NULL);
|
||||
#else
|
||||
INIT_LOCK(_request_ready_lock);
|
||||
pthread_cond_init(&_request_ready_cvar, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
// Ensure the appropriate Windows common controls are available to
|
||||
// this application.
|
||||
@ -68,13 +60,6 @@ P3DInstanceManager::
|
||||
|
||||
assert(_instances.empty());
|
||||
assert(_sessions.empty());
|
||||
|
||||
#ifdef _WIN32
|
||||
CloseHandle(_request_ready);
|
||||
#else
|
||||
DESTROY_LOCK(_request_ready_lock);
|
||||
pthread_cond_destroy(&_request_ready_cvar);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -211,30 +196,21 @@ check_request() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstanceManager::
|
||||
wait_request() {
|
||||
int seq = _request_seq;
|
||||
|
||||
_request_ready.acquire();
|
||||
while (true) {
|
||||
if (check_request() != (P3DInstance *)NULL) {
|
||||
_request_ready.release();
|
||||
return;
|
||||
}
|
||||
if (_instances.empty()) {
|
||||
_request_ready.release();
|
||||
return;
|
||||
}
|
||||
|
||||
// No pending requests; go to sleep.
|
||||
#ifdef _WIN32
|
||||
if (seq == _request_seq) {
|
||||
WaitForSingleObject(_request_ready, INFINITE);
|
||||
}
|
||||
#else
|
||||
ACQUIRE_LOCK(_request_ready_lock);
|
||||
if (seq == _request_seq) {
|
||||
pthread_cond_wait(&_request_ready_cvar, &_request_ready_lock);
|
||||
}
|
||||
RELEASE_LOCK(_request_ready_lock);
|
||||
#endif
|
||||
seq = _request_seq;
|
||||
_request_ready.wait();
|
||||
}
|
||||
_request_ready.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -283,15 +259,9 @@ get_unique_session_index() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstanceManager::
|
||||
signal_request_ready() {
|
||||
#ifdef _WIN32
|
||||
++_request_seq;
|
||||
SetEvent(_request_ready);
|
||||
#else
|
||||
ACQUIRE_LOCK(_request_ready_lock);
|
||||
++_request_seq;
|
||||
pthread_cond_signal(&_request_ready_cvar);
|
||||
RELEASE_LOCK(_request_ready_lock);
|
||||
#endif
|
||||
_request_ready.acquire();
|
||||
_request_ready.notify();
|
||||
_request_ready.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define P3DINSTANCEMANAGER_H
|
||||
|
||||
#include "p3d_plugin_common.h"
|
||||
#include "p3dConditionVar.h"
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
@ -83,14 +84,7 @@ private:
|
||||
|
||||
int _unique_session_index;
|
||||
|
||||
// Implements a condition-var like behavior.
|
||||
volatile int _request_seq;
|
||||
#ifdef _WIN32
|
||||
HANDLE _request_ready;
|
||||
#else
|
||||
LOCK _request_ready_lock;
|
||||
pthread_cond_t _request_ready_cvar;
|
||||
#endif
|
||||
P3DConditionVar _request_ready;
|
||||
static P3DInstanceManager *_global_ptr;
|
||||
};
|
||||
|
||||
|
@ -192,9 +192,17 @@ handle_command(TiXmlDocument *doc) {
|
||||
nout << "got command: " << *doc << "\n";
|
||||
TiXmlElement *xcommand = doc->FirstChildElement("command");
|
||||
if (xcommand != NULL) {
|
||||
bool needs_response = false;
|
||||
int want_response_id;
|
||||
if (xcommand->QueryIntAttribute("want_response_id", &want_response_id) == TIXML_SUCCESS) {
|
||||
// This command will be waiting for a response.
|
||||
needs_response = true;
|
||||
}
|
||||
|
||||
const char *cmd = xcommand->Attribute("cmd");
|
||||
if (cmd != NULL) {
|
||||
if (strcmp(cmd, "start_instance") == 0) {
|
||||
assert(!needs_response);
|
||||
TiXmlElement *xinstance = xcommand->FirstChildElement("instance");
|
||||
if (xinstance != (TiXmlElement *)NULL) {
|
||||
P3DCInstance *inst = new P3DCInstance(xinstance);
|
||||
@ -202,12 +210,14 @@ handle_command(TiXmlDocument *doc) {
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd, "terminate_instance") == 0) {
|
||||
assert(!needs_response);
|
||||
int instance_id;
|
||||
if (xcommand->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS) {
|
||||
terminate_instance(instance_id);
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd, "setup_window") == 0) {
|
||||
assert(!needs_response);
|
||||
int instance_id;
|
||||
TiXmlElement *xwparams = xcommand->FirstChildElement("wparams");
|
||||
if (xwparams != (TiXmlElement *)NULL &&
|
||||
@ -216,34 +226,61 @@ handle_command(TiXmlDocument *doc) {
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd, "exit") == 0) {
|
||||
assert(!needs_response);
|
||||
terminate_session();
|
||||
|
||||
} else if (strcmp(cmd, "feed_value") == 0) {
|
||||
int instance_id, unique_id;
|
||||
if (xcommand->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS &&
|
||||
xcommand->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) {
|
||||
// TODO: deal with instance_id.
|
||||
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
|
||||
if (xvalue != NULL) {
|
||||
PyObject *value = from_xml_value(xvalue);
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char*)"feedValue", (char*)"iOi", unique_id, value, true);
|
||||
Py_DECREF(value);
|
||||
Py_XDECREF(result);
|
||||
} else {
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char*)"feedValue", (char*)"iOi", unique_id, Py_None, false);
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
}
|
||||
} else if (strcmp(cmd, "pyobj") == 0) {
|
||||
// Manipulate or query a python object. Presumably this
|
||||
// command will want a response.
|
||||
assert(needs_response);
|
||||
|
||||
handle_pyobj_command(xcommand, want_response_id);
|
||||
|
||||
} else {
|
||||
nout << "Unhandled command " << cmd << "\n";
|
||||
if (needs_response) {
|
||||
// Better send a response.
|
||||
TiXmlDocument doc;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xresponse = new TiXmlElement("response");
|
||||
xresponse->SetAttribute("response_id", want_response_id);
|
||||
doc.LinkEndChild(decl);
|
||||
doc.LinkEndChild(xresponse);
|
||||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::handle_pyobj_command
|
||||
// Access: Private
|
||||
// Description: Handles the pyobj command, which queries or modifies
|
||||
// a Python object from the browser scripts.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DPythonRun::
|
||||
handle_pyobj_command(TiXmlElement *xcommand, int want_response_id) {
|
||||
TiXmlDocument doc;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xresponse = new TiXmlElement("response");
|
||||
xresponse->SetAttribute("response_id", want_response_id);
|
||||
doc.LinkEndChild(decl);
|
||||
doc.LinkEndChild(xresponse);
|
||||
|
||||
const char *op = xcommand->Attribute("op");
|
||||
if (op != NULL) {
|
||||
if (strcmp(op, "get_script_object") == 0) {
|
||||
// Get the toplevel Python object.
|
||||
xresponse->SetAttribute("object", "fooby");
|
||||
}
|
||||
}
|
||||
|
||||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonRun::check_comm
|
||||
// Access: Private
|
||||
|
@ -70,6 +70,8 @@ public:
|
||||
|
||||
private:
|
||||
void handle_command(TiXmlDocument *doc);
|
||||
void handle_pyobj_command(TiXmlElement *xcommand, int want_response_id);
|
||||
|
||||
AsyncTask::DoneStatus check_comm(GenericAsyncTask *task);
|
||||
static AsyncTask::DoneStatus st_check_comm(GenericAsyncTask *task, void *user_data);
|
||||
|
||||
|
@ -36,6 +36,10 @@ P3DSession(P3DInstance *inst) {
|
||||
_python_version = inst->get_python_version();
|
||||
|
||||
_p3dpython_running = false;
|
||||
_next_response_id = 0;
|
||||
_response = NULL;
|
||||
_got_response_id = -1;
|
||||
|
||||
_started_read_thread = false;
|
||||
_read_thread_continue = false;
|
||||
|
||||
@ -210,6 +214,78 @@ send_command(TiXmlDocument *command) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::command_and_response
|
||||
// Access: Public
|
||||
// Description: Sends the indicated command to the running Python
|
||||
// process, and waits for a response. Returns the
|
||||
// newly-allocated response on success, or NULL on
|
||||
// failure.
|
||||
//
|
||||
// The command must be a newly-allocated TiXmlDocument;
|
||||
// it will be deleted after it has been delivered to the
|
||||
// process.
|
||||
//
|
||||
// This will fail if the python process is not running
|
||||
// or if it suddenly stops.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TiXmlDocument *P3DSession::
|
||||
command_and_response(TiXmlDocument *command) {
|
||||
if (!_p3dpython_running) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int response_id = _next_response_id;
|
||||
++_next_response_id;
|
||||
|
||||
// Add the "want_response_id" attribute to the toplevel command, so
|
||||
// the sub-process knows we'll be waiting for its response.
|
||||
TiXmlElement *xcommand = command->FirstChildElement("command");
|
||||
assert(xcommand != NULL);
|
||||
xcommand->SetAttribute("want_response_id", response_id);
|
||||
|
||||
_pipe_write << *command << flush;
|
||||
delete command;
|
||||
|
||||
// Now block, waiting for a response to be delivered. We assume
|
||||
// only one thread will be waiting at a time.
|
||||
nout << "Waiting for response " << response_id << "\n" << flush;
|
||||
_response_ready.acquire();
|
||||
while (_response == NULL || _got_response_id != response_id) {
|
||||
if (_response != NULL) {
|
||||
// This is a bogus response. Since we're the only thread waiting,
|
||||
// it follows that no one is waiting for this response, so we can
|
||||
// throw it away.
|
||||
nout << "Discarding bogus response: " << *_response << "\n";
|
||||
delete _response;
|
||||
_response = NULL;
|
||||
_got_response_id = -1;
|
||||
}
|
||||
|
||||
if (!_p3dpython_running) {
|
||||
// Hmm, looks like Python has gone away.
|
||||
|
||||
// TODO: make sure _p3dpython_running gets set to false when the
|
||||
// process dies unexpectedly.
|
||||
_response_ready.release();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_response_ready.wait();
|
||||
}
|
||||
// When we exit the loop, we've found the desired response.
|
||||
|
||||
TiXmlDocument *response = _response;
|
||||
_response = NULL;
|
||||
_got_response_id = -1;
|
||||
|
||||
_response_ready.release();
|
||||
|
||||
nout << "Got response: " << *response << "\n" << flush;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::install_progress
|
||||
// Access: Private
|
||||
@ -316,6 +392,22 @@ start_p3dpython() {
|
||||
}
|
||||
_pipe_write << flush;
|
||||
_commands.clear();
|
||||
|
||||
// Temp testing code.
|
||||
{
|
||||
TiXmlDocument *doc = new TiXmlDocument;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
|
||||
TiXmlElement *xcommand = new TiXmlElement("command");
|
||||
xcommand->SetAttribute("cmd", "pyobj");
|
||||
xcommand->SetAttribute("op", "get");
|
||||
doc->LinkEndChild(decl);
|
||||
doc->LinkEndChild(xcommand);
|
||||
TiXmlDocument *response = command_and_response(doc);
|
||||
nout << "response pointer: " << response << "\n";
|
||||
if (response != NULL) {
|
||||
delete response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -409,10 +501,33 @@ void P3DSession::
|
||||
rt_handle_request(TiXmlDocument *doc) {
|
||||
nout << "Session got request: " << *doc << "\n" << flush;
|
||||
|
||||
TiXmlElement *xresponse = doc->FirstChildElement("response");
|
||||
if (xresponse != (TiXmlElement *)NULL) {
|
||||
int response_id;
|
||||
if (xresponse->QueryIntAttribute("response_id", &response_id) == TIXML_SUCCESS) {
|
||||
// This is a response to a previous command-and-response. Send
|
||||
// it to the parent thread.
|
||||
_response_ready.acquire();
|
||||
if (_response != NULL) {
|
||||
// Hey, there's already a response there. Since there's only
|
||||
// one thread waiting at a time on the command-response cycle,
|
||||
// this must be a bogus response that never got picked up.
|
||||
// Discard it.
|
||||
nout << "Discarding bogus response: " << *_response << "\n";
|
||||
delete _response;
|
||||
}
|
||||
_response = doc;
|
||||
_got_response_id = response_id;
|
||||
_response_ready.notify();
|
||||
_response_ready.release();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TiXmlElement *xrequest = doc->FirstChildElement("request");
|
||||
if (xrequest != (TiXmlElement *)NULL) {
|
||||
int instance_id ;
|
||||
if (xrequest->Attribute("instance_id", &instance_id)) {
|
||||
int instance_id;
|
||||
if (xrequest->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS) {
|
||||
// Look up the particular instance this is related to.
|
||||
ACQUIRE_LOCK(_instances_lock);
|
||||
Instances::const_iterator ii;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "p3d_plugin_common.h"
|
||||
#include "handleStream.h"
|
||||
#include "p3dPackage.h"
|
||||
#include "p3dConditionVar.h"
|
||||
#include "get_tinyxml.h"
|
||||
|
||||
#include <map>
|
||||
@ -47,6 +48,7 @@ public:
|
||||
inline int get_num_instances() const;
|
||||
|
||||
void send_command(TiXmlDocument *command);
|
||||
TiXmlDocument *command_and_response(TiXmlDocument *command);
|
||||
|
||||
private:
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
@ -120,6 +122,13 @@ private:
|
||||
#endif
|
||||
bool _p3dpython_running;
|
||||
|
||||
int _next_response_id;
|
||||
|
||||
// The _response_ready mutex protects this pointer.
|
||||
TiXmlDocument *_response;
|
||||
int _got_response_id;
|
||||
P3DConditionVar _response_ready;
|
||||
|
||||
// The remaining members are manipulated by or for the read thread.
|
||||
bool _started_read_thread;
|
||||
HandleStream _pipe_read;
|
||||
|
@ -1,20 +1,20 @@
|
||||
#include "p3d_plugin.cxx"
|
||||
#include "p3dBoolObject.cxx"
|
||||
#include "p3dConditionVar.cxx"
|
||||
#include "p3dDownload.cxx"
|
||||
#include "p3dFileDownload.cxx"
|
||||
#include "p3dFileParams.cxx"
|
||||
#include "p3dFloatObject.cxx"
|
||||
#include "p3dInstance.cxx"
|
||||
#include "p3dInstanceManager.cxx"
|
||||
#include "p3dIntObject.cxx"
|
||||
#include "p3dListObject.cxx"
|
||||
#include "p3dMultifileReader.cxx"
|
||||
#include "p3dNoneObject.cxx"
|
||||
#include "p3dPackage.cxx"
|
||||
#include "p3dSplashWindow.cxx"
|
||||
#include "p3dSession.cxx"
|
||||
#include "p3dWindowParams.cxx"
|
||||
#include "p3dWinSplashWindow.cxx"
|
||||
#include "p3dObject.cxx"
|
||||
#include "p3dBoolObject.cxx"
|
||||
#include "p3dIntObject.cxx"
|
||||
#include "p3dFloatObject.cxx"
|
||||
#include "p3dListObject.cxx"
|
||||
#include "p3dPackage.cxx"
|
||||
#include "p3dSession.cxx"
|
||||
#include "p3dSplashWindow.cxx"
|
||||
#include "p3dStringObject.cxx"
|
||||
|
||||
#include "p3dWinSplashWindow.cxx"
|
||||
#include "p3dWindowParams.cxx"
|
||||
|
Loading…
x
Reference in New Issue
Block a user