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

Reply via email to