diff options
author | Mark Spruiell <mes@zeroc.com> | 2017-03-07 15:25:46 -0800 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2017-03-07 15:25:46 -0800 |
commit | a6cc8dc5ed35ce0f4afcaddcdaad912bc5816556 (patch) | |
tree | 94038b3144884505db5c41006d231b5a2ae2ca3e /python/modules | |
parent | Missing CSharp Glacier2/application test (diff) | |
download | ice-a6cc8dc5ed35ce0f4afcaddcdaad912bc5816556.tar.bz2 ice-a6cc8dc5ed35ce0f4afcaddcdaad912bc5816556.tar.xz ice-a6cc8dc5ed35ce0f4afcaddcdaad912bc5816556.zip |
ICE-6845 - add Python support for dispatcher
Diffstat (limited to 'python/modules')
-rw-r--r-- | python/modules/IcePy/BatchRequestInterceptor.cpp | 1 | ||||
-rw-r--r-- | python/modules/IcePy/Communicator.cpp | 22 | ||||
-rw-r--r-- | python/modules/IcePy/Dispatcher.cpp | 163 | ||||
-rw-r--r-- | python/modules/IcePy/Dispatcher.h | 42 | ||||
-rw-r--r-- | python/modules/IcePy/Init.cpp | 5 |
5 files changed, 233 insertions, 0 deletions
diff --git a/python/modules/IcePy/BatchRequestInterceptor.cpp b/python/modules/IcePy/BatchRequestInterceptor.cpp index b4d36366ee1..95e7ed1345a 100644 --- a/python/modules/IcePy/BatchRequestInterceptor.cpp +++ b/python/modules/IcePy/BatchRequestInterceptor.cpp @@ -257,6 +257,7 @@ IcePy::BatchRequestInterceptor::enqueue(const Ice::BatchRequest& request, int qu obj->proxy = 0; PyObjectHandle tmp = PyObject_CallMethod(_interceptor.get(), STRCAST("enqueue"), STRCAST("Oii"), obj, queueCount, queueSize); + Py_DECREF(reinterpret_cast<PyObject*>(obj)); if(!tmp.get()) { throwPythonException(); diff --git a/python/modules/IcePy/Communicator.cpp b/python/modules/IcePy/Communicator.cpp index 63d19e7634d..56ffebabc9c 100644 --- a/python/modules/IcePy/Communicator.cpp +++ b/python/modules/IcePy/Communicator.cpp @@ -13,6 +13,7 @@ #include <IceUtil/DisableWarnings.h> #include <Communicator.h> #include <BatchRequestInterceptor.h> +#include <Dispatcher.h> #include <ImplicitContext.h> #include <Logger.h> #include <ObjectAdapter.h> @@ -59,6 +60,7 @@ struct CommunicatorObject IceUtil::Monitor<IceUtil::Mutex>* shutdownMonitor; WaitForShutdownThreadPtr* shutdownThread; bool shutdown; + DispatcherPtr* dispatcher; }; } @@ -80,6 +82,7 @@ communicatorNew(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/) self->shutdownMonitor = new IceUtil::Monitor<IceUtil::Mutex>; self->shutdownThread = 0; self->shutdown = false; + self->dispatcher = 0; return self; } @@ -142,6 +145,7 @@ communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/) bool hasArgs = argList != 0; Ice::InitializationData data; + DispatcherPtr dispatcherWrapper; if(initData) { @@ -149,6 +153,7 @@ communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/) PyObjectHandle logger = PyObject_GetAttrString(initData, STRCAST("logger")); PyObjectHandle threadHook = PyObject_GetAttrString(initData, STRCAST("threadHook")); PyObjectHandle batchRequestInterceptor = PyObject_GetAttrString(initData, STRCAST("batchRequestInterceptor")); + PyObjectHandle dispatcher = PyObject_GetAttrString(initData, STRCAST("dispatcher")); PyErr_Clear(); // PyObject_GetAttrString sets an error on failure. @@ -172,6 +177,12 @@ communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/) data.threadHook = new ThreadHook(threadHook.get()); } + if(dispatcher.get() && dispatcher.get() != Py_None) + { + dispatcherWrapper = new Dispatcher(dispatcher.get()); + data.dispatcher = dispatcherWrapper; + } + if(batchRequestInterceptor.get() && batchRequestInterceptor.get() != Py_None) { data.batchRequestInterceptor = new BatchRequestInterceptor(batchRequestInterceptor.get()); @@ -269,6 +280,12 @@ communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/) } _communicatorMap.insert(CommunicatorMap::value_type(communicator, reinterpret_cast<PyObject*>(self))); + if(dispatcherWrapper) + { + self->dispatcher = new DispatcherPtr(dispatcherWrapper); + dispatcherWrapper->setCommunicator(communicator); + } + return 0; } @@ -323,6 +340,11 @@ communicatorDestroy(CommunicatorObject* self) vfm->destroy(); + if(self->dispatcher) + { + (*self->dispatcher)->setCommunicator(0); // Break cyclic reference. + } + // // Break cyclic reference between this object and its Python wrapper. // diff --git a/python/modules/IcePy/Dispatcher.cpp b/python/modules/IcePy/Dispatcher.cpp new file mode 100644 index 00000000000..06a6d39c991 --- /dev/null +++ b/python/modules/IcePy/Dispatcher.cpp @@ -0,0 +1,163 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifdef _WIN32 +# include <IceUtil/Config.h> +#endif +#include <Dispatcher.h> +#include <Connection.h> +#include <Thread.h> +#include <Ice/Initialize.h> + +using namespace std; +using namespace IcePy; + +namespace IcePy +{ + +struct DispatcherCallObject +{ + PyObject_HEAD + Ice::DispatcherCallPtr* call; +}; + +} + +#ifdef WIN32 +extern "C" +#endif +static void +dispatcherCallDealloc(DispatcherCallObject* self) +{ + delete self->call; + Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* +dispatcherCallInvoke(DispatcherCallObject* self, PyObject* /*args*/, PyObject* /*kwds*/) +{ + AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls. + + try + { + (*self->call)->run(); + } + catch(const Ice::Exception& ex) + { + setPythonException(ex); + return 0; + } + + return incRef(Py_None); +} + +namespace IcePy +{ + +PyTypeObject DispatcherCallType = +{ + /* The ob_type field must be initialized in the module init function + * to be portable to Windows without using C++. */ + PyVarObject_HEAD_INIT(0, 0) + STRCAST("IcePy.DispatcherCall"), /* tp_name */ + sizeof(DispatcherCallObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + reinterpret_cast<destructor>(dispatcherCallDealloc), /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + reinterpret_cast<ternaryfunc>(dispatcherCallInvoke), /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +} + +bool +IcePy::initDispatcher(PyObject* module) +{ + if(PyType_Ready(&DispatcherCallType) < 0) + { + return false; + } + PyTypeObject* type = &DispatcherCallType; // Necessary to prevent GCC's strict-alias warnings. + if(PyModule_AddObject(module, STRCAST("DispatcherCall"), reinterpret_cast<PyObject*>(type)) < 0) + { + return false; + } + + return true; +} + +IcePy::Dispatcher::Dispatcher(PyObject* dispatcher) : + _dispatcher(dispatcher) +{ + Py_INCREF(dispatcher); +} + +void +IcePy::Dispatcher::setCommunicator(const Ice::CommunicatorPtr& communicator) +{ + _communicator = communicator; +} + +void +IcePy::Dispatcher::dispatch(const Ice::DispatcherCallPtr& call, const Ice::ConnectionPtr& con) +{ + AdoptThread adoptThread; // Ensure the current thread is able to call into Python. + + DispatcherCallObject* obj = + reinterpret_cast<DispatcherCallObject*>(DispatcherCallType.tp_alloc(&DispatcherCallType, 0)); + if(!obj) + { + return; + } + + obj->call = new Ice::DispatcherCallPtr(call); + PyObjectHandle c = createConnection(con, _communicator); + PyObjectHandle tmp = PyObject_CallMethod(_dispatcher.get(), STRCAST("dispatch"), STRCAST("OO"), obj, c); + Py_DECREF(reinterpret_cast<PyObject*>(obj)); + if(!tmp.get()) + { + throwPythonException(); + } +} diff --git a/python/modules/IcePy/Dispatcher.h b/python/modules/IcePy/Dispatcher.h new file mode 100644 index 00000000000..156dac95bba --- /dev/null +++ b/python/modules/IcePy/Dispatcher.h @@ -0,0 +1,42 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPY_DISPATCHER_H +#define ICEPY_DISPATCHER_H + +#include <Config.h> +#include <Util.h> +#include <Ice/CommunicatorF.h> +#include <Ice/Dispatcher.h> + +namespace IcePy +{ + +bool initDispatcher(PyObject*); + +class Dispatcher : public Ice::Dispatcher +{ +public: + + Dispatcher(PyObject*); + + void setCommunicator(const Ice::CommunicatorPtr&); + + virtual void dispatch(const Ice::DispatcherCallPtr&, const Ice::ConnectionPtr&); + +private: + + PyObjectHandle _dispatcher; + Ice::CommunicatorPtr _communicator; +}; +typedef IceUtil::Handle<Dispatcher> DispatcherPtr; + +} + +#endif diff --git a/python/modules/IcePy/Init.cpp b/python/modules/IcePy/Init.cpp index 35caf6a9e15..fe1db336962 100644 --- a/python/modules/IcePy/Init.cpp +++ b/python/modules/IcePy/Init.cpp @@ -15,6 +15,7 @@ #include <Connection.h> #include <ConnectionInfo.h> #include <Current.h> +#include <Dispatcher.h> #include <Endpoint.h> #include <EndpointInfo.h> #include <ImplicitContext.h> @@ -184,6 +185,10 @@ initIcePy(void) { INIT_RETURN; } + if(!initDispatcher(module)) + { + INIT_RETURN; + } if(!initBatchRequest(module)) { INIT_RETURN; |