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.
_______________________________________________
SyncEvolution mailing list
[email protected]
http://lists.syncevolution.org/listinfo/syncevolution