summaryrefslogtreecommitdiff
path: root/python/modules/IcePy/Connection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'python/modules/IcePy/Connection.cpp')
-rw-r--r--python/modules/IcePy/Connection.cpp159
1 files changed, 116 insertions, 43 deletions
diff --git a/python/modules/IcePy/Connection.cpp b/python/modules/IcePy/Connection.cpp
index 736b54a1416..2f5998bffc9 100644
--- a/python/modules/IcePy/Connection.cpp
+++ b/python/modules/IcePy/Connection.cpp
@@ -37,18 +37,18 @@ struct ConnectionObject
Ice::CommunicatorPtr* communicator;
};
-class ConnectionCallbackI : public Ice::ConnectionCallback
+class CloseCallbackI : public Ice::CloseCallback
{
public:
- ConnectionCallbackI(PyObject* cb, PyObject* con) :
+ CloseCallbackI(PyObject* cb, PyObject* con) :
_cb(cb), _con(con)
{
Py_INCREF(cb);
Py_INCREF(con);
}
- virtual ~ConnectionCallbackI()
+ virtual ~CloseCallbackI()
{
AdoptThread adoptThread; // Ensure the current thread is able to call into Python.
@@ -56,52 +56,94 @@ public:
Py_DECREF(_con);
}
- virtual void heartbeat(const Ice::ConnectionPtr& con)
- {
- invoke("heartbeat", con);
- }
-
virtual void closed(const Ice::ConnectionPtr& con)
{
- invoke("closed", con);
+ invoke(con);
}
private:
- void invoke(const string& methodName, const Ice::ConnectionPtr& con)
+ void invoke(const Ice::ConnectionPtr& con)
{
AdoptThread adoptThread; // Ensure the current thread is able to call into Python.
#ifndef NDEBUG
ConnectionObject* c = reinterpret_cast<ConnectionObject*>(_con);
assert(con == *(c->connection));
#endif
- if(!PyObject_HasAttrString(_cb, STRCAST(methodName.c_str())))
+
+ PyObjectHandle args = Py_BuildValue(STRCAST("(O)"), _con);
+ assert(_cb);
+ PyObjectHandle tmp = PyObject_Call(_cb, args.get(), 0);
+ if(PyErr_Occurred())
{
- ostringstream ostr;
- ostr << "connection callback object does not define " << methodName << "()";
- string str = ostr.str();
- PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()));
+ PyException ex; // Retrieve it before another Python API call clears it.
+
+ //
+ // A callback that calls sys.exit() will raise the SystemExit exception.
+ // This is normally caught by the interpreter, causing it to exit.
+ // However, we have no way to pass this exception to the interpreter,
+ // so we act on it directly.
+ //
+ ex.checkSystemExit();
+
+ ex.raise();
}
- else
+ }
+
+ PyObject* _cb;
+ PyObject* _con;
+};
+
+class HeartbeatCallbackI : public Ice::HeartbeatCallback
+{
+public:
+
+ HeartbeatCallbackI(PyObject* cb, PyObject* con) :
+ _cb(cb), _con(con)
+ {
+ Py_INCREF(cb);
+ Py_INCREF(con);
+ }
+
+ virtual ~HeartbeatCallbackI()
+ {
+ AdoptThread adoptThread; // Ensure the current thread is able to call into Python.
+
+ Py_DECREF(_cb);
+ Py_DECREF(_con);
+ }
+
+ virtual void heartbeat(const Ice::ConnectionPtr& con)
+ {
+ invoke(con);
+ }
+
+private:
+
+ void invoke(const Ice::ConnectionPtr& con)
+ {
+ AdoptThread adoptThread; // Ensure the current thread is able to call into Python.
+#ifndef NDEBUG
+ ConnectionObject* c = reinterpret_cast<ConnectionObject*>(_con);
+ assert(con == *(c->connection));
+#endif
+
+ PyObjectHandle args = Py_BuildValue(STRCAST("(O)"), _con);
+ assert(_cb);
+ PyObjectHandle tmp = PyObject_Call(_cb, args.get(), 0);
+ if(PyErr_Occurred())
{
- PyObjectHandle args = Py_BuildValue(STRCAST("(O)"), _con);
- PyObjectHandle method = PyObject_GetAttrString(_cb, STRCAST(methodName.c_str()));
- assert(method.get());
- PyObjectHandle tmp = PyObject_Call(method.get(), args.get(), 0);
- if(PyErr_Occurred())
- {
- PyException ex; // Retrieve it before another Python API call clears it.
-
- //
- // A callback that calls sys.exit() will raise the SystemExit exception.
- // This is normally caught by the interpreter, causing it to exit.
- // However, we have no way to pass this exception to the interpreter,
- // so we act on it directly.
- //
- ex.checkSystemExit();
-
- ex.raise();
- }
+ PyException ex; // Retrieve it before another Python API call clears it.
+
+ //
+ // A callback that calls sys.exit() will raise the SystemExit exception.
+ // This is normally caught by the interpreter, causing it to exit.
+ // However, we have no way to pass this exception to the interpreter,
+ // so we act on it directly.
+ //
+ ex.checkSystemExit();
+
+ ex.raise();
}
}
@@ -190,9 +232,7 @@ connectionCompare(ConnectionObject* c1, PyObject* other, int op)
}
}
- PyObject* r = result ? getTrue() : getFalse();
- Py_INCREF(r);
- return r;
+ return result ? incTrue() : incFalse();
}
#ifdef WIN32
@@ -437,22 +477,53 @@ connectionEndFlushBatchRequests(ConnectionObject* self, PyObject* args)
extern "C"
#endif
static PyObject*
-connectionSetCallback(ConnectionObject* self, PyObject* args)
+connectionSetCloseCallback(ConnectionObject* self, PyObject* args)
+{
+ assert(self->connection);
+
+ PyObject* callbackType = lookupType("types.FunctionType");
+ PyObject* cb;
+ if(!PyArg_ParseTuple(args, STRCAST("O!"), callbackType, &cb))
+ {
+ return 0;
+ }
+
+ Ice::CloseCallbackPtr wrapper = new CloseCallbackI(cb, reinterpret_cast<PyObject*>(self));
+ try
+ {
+ AllowThreads allowThreads; // Release Python's global interpreter lock during blocking invocations.
+ (*self->connection)->setCloseCallback(wrapper);
+ }
+ catch(const Ice::Exception& ex)
+ {
+ setPythonException(ex);
+ return 0;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef WIN32
+extern "C"
+#endif
+static PyObject*
+connectionSetHeartbeatCallback(ConnectionObject* self, PyObject* args)
{
assert(self->connection);
- PyObject* callbackType = lookupType("Ice.ConnectionCallback");
+ PyObject* callbackType = lookupType("types.FunctionType");
PyObject* cb;
if(!PyArg_ParseTuple(args, STRCAST("O!"), callbackType, &cb))
{
return 0;
}
- Ice::ConnectionCallbackPtr wrapper = new ConnectionCallbackI(cb, reinterpret_cast<PyObject*>(self));
+ Ice::HeartbeatCallbackPtr wrapper = new HeartbeatCallbackI(cb, reinterpret_cast<PyObject*>(self));
try
{
AllowThreads allowThreads; // Release Python's global interpreter lock during blocking invocations.
- (*self->connection)->setCallback(wrapper);
+ (*self->connection)->setHeartbeatCallback(wrapper);
}
catch(const Ice::Exception& ex)
{
@@ -754,8 +825,10 @@ static PyMethodDef ConnectionMethods[] =
METH_VARARGS | METH_KEYWORDS, PyDoc_STR(STRCAST("begin_flushBatchRequests([_ex][, _sent]) -> Ice.AsyncResult")) },
{ STRCAST("end_flushBatchRequests"), reinterpret_cast<PyCFunction>(connectionEndFlushBatchRequests), METH_VARARGS,
PyDoc_STR(STRCAST("end_flushBatchRequests(Ice.AsyncResult) -> None")) },
- { STRCAST("setCallback"), reinterpret_cast<PyCFunction>(connectionSetCallback), METH_VARARGS,
- PyDoc_STR(STRCAST("setCallback(Ice.ConnectionCallback) -> None")) },
+ { STRCAST("setCloseCallback"), reinterpret_cast<PyCFunction>(connectionSetCloseCallback), METH_VARARGS,
+ PyDoc_STR(STRCAST("setCloseCallback(Ice.CloseCallback) -> None")) },
+ { STRCAST("setHeartbeatCallback"), reinterpret_cast<PyCFunction>(connectionSetHeartbeatCallback), METH_VARARGS,
+ PyDoc_STR(STRCAST("setHeartbeatCallback(Ice.HeartbeatCallback) -> None")) },
{ STRCAST("setACM"), reinterpret_cast<PyCFunction>(connectionSetACM), METH_VARARGS,
PyDoc_STR(STRCAST("setACM(int, Ice.ACMClose, Ice.ACMHeartbeat) -> None")) },
{ STRCAST("getACM"), reinterpret_cast<PyCFunction>(connectionGetACM), METH_NOARGS,