On Tue, 2012-02-14 at 16:02 +0100, Patrick Ohly wrote:
On Mon, 2012-02-13 at 14:50 +0100, Chris Kühl wrote:
> - Krzesimir implemented the missing functionality in the gio-gdbus
> wrapper and added code to do blocking calls with minimal extra code
> required in consuming classes.
In addition to adding a block() method which executes the call, wouldn't
it be nicer to also overload the call operator such that if there is no
Callback_t parameter, all results are returned directly (special case
for a single return value) or as tuple (general case)?
The block() call would be more efficient for large return values (avoids
one copying), but for small ones the ease of use certainly would be
worth it.
I've experimented a bit with it and think it can be done.
Is there still a need for the block() variant if there was a "normal"
blocking call operator()?
Here's a partial implementation. Not all combinations of number of
parameters and return values are currently spelled out. Is there a
better approach and would it be worthwhile?
diff --git a/src/gdbus/gdbus-cxx-bridge.h b/src/gdbus/gdbus-cxx-bridge.h
index dc217ca..d56be89 100644
--- a/src/gdbus/gdbus-cxx-bridge.h
+++ b/src/gdbus/gdbus-cxx-bridge.h
@@ -81,6 +81,7 @@ static inline void intrusive_ptr_release(DBusServer
*server) { dbus_server_unref
#include <boost/variant.hpp>
#include <boost/variant/get.hpp>
#include <boost/utility.hpp>
+#include <boost/tuple/tuple.hpp>
/* The connection is the only client-exposed type from the C API. To
* keep changes to a minimum while supporting both dbus
@@ -3913,6 +3914,20 @@ protected:
typedef T Callback_t;
+ /**
+ * Blocking method call: execute call and check for error.
+ * Encoding parameters and decoding return values must be done by
+ * caller.
+ */
+ void doCall(DBusMessagePtr &msg, DBusMessagePtr &reply)
+ {
+ DBusErrorCXX error;
+ reply =
dbus_connection_send_with_reply_and_block(DBusClientCall<Callback_t>::m_conn.get(),
msg.get(), -1, &error);
+ if (!reply) {
+ error.throwFailure(DBusClientCall<Callback_t>::m_method);
+ }
+ }
+
void prepare(DBusMessagePtr &msg)
{
// Constructor steals reference, reset() doesn't!
@@ -4225,6 +4240,20 @@ public:
: DBusClientCall<Callback_t>(object, method,
&DBusClientCall0::dbusCallback)
{
}
+
+ // keep call operator from base class visible
+ using DBusClientCall<Callback_t>::operator ();
+
+ // return once the call is done, throws runtime_error if it fails
+ template <class A1>
+ void operator () (const A1 &a1)
+ {
+ DBusMessagePtr msg;
+ prepare(msg);
+ AppendRetvals(msg) << a1;
+ DBusMessagePtr reply;
+ DBusClientCall<Callback_t>::doCall(msg, reply);
+ }
};
/** 1 return value and 0 or more parameters */
@@ -4257,6 +4286,24 @@ public:
: DBusClientCall<Callback_t>(object, method,
&DBusClientCall1::dbusCallback)
{
}
+
+ using DBusClientCall<Callback_t>::operator ();
+
+ template <class A1>
+ R1 operator () (const A1 &a1)
+ {
+ DBusMessagePtr msg;
+ DBusClientCall<Callback_t>::prepare(msg);
+ AppendRetvals(msg) << a1;
+ DBusErrorCXX error;
+ DBusMessagePtr reply =
dbus_connection_send_with_reply_and_block(DBusClientCall<Callback_t>::m_conn.get(),
msg.get(), -1, &error);
+ if (!reply) {
+ error.throwFailure(DBusClientCall<Callback_t>::m_method);
+ }
+ typename dbus_traits<R1>::host_type r;
+ ExtractArgs(DBusClientCall<Callback_t>::m_conn.get(),
reply.get()) >> Get<R1>(r);
+ return r;
+ }
};
/** 2 return value and 0 or more parameters */
@@ -4291,6 +4338,34 @@ public:
: DBusClientCall<Callback_t>(object, method,
&DBusClientCall2::dbusCallback)
{
}
+
+ using DBusClientCall<Callback_t>::operator ();
+
+ boost::tuple<R1, R2> operator () ()
+ {
+ DBusMessagePtr msg;
+ DBusClientCall<Callback_t>::prepare(msg);
+ DBusMessagePtr reply;
+ DBusClientCall<Callback_t>::doCall(msg, reply);
+ boost::tuple<R1, R2> r;
+ boost::get<0>(r);
+ ExtractArgs(DBusClientCall<Callback_t>::m_conn.get(),
reply.get()) >> Get<R1>(boost::get<0>(r)) >>
Get<R2>(boost::get<1>(r));
+ return r;
+ }
+
+ template <class A1>
+ boost::tuple<R1, R2> operator () (const A1 &a1)
+ {
+ DBusMessagePtr msg;
+ DBusClientCall<Callback_t>::prepare(msg);
+ AppendRetvals(msg) << a1;
+ DBusMessagePtr reply;
+ DBusClientCall<Callback_t>::doCall(msg, reply);
+ boost::tuple<R1, R2> r;
+ ExtractArgs(DBusClientCall<Callback_t>::m_conn.get(),
reply.get()) >> Get<R1>(r[0]) >> Get<R2>(r[1]);
+ return r;
+ }
+
};
/** 3 return value and 0 or more parameters */
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.