diff --git a/src/dbus/server/pim/folks.cpp b/src/dbus/server/pim/folks.cpp index 13f4f563..9eb6dda6 100644 --- a/src/dbus/server/pim/folks.cpp +++ b/src/dbus/server/pim/folks.cpp @@ -862,7 +862,7 @@ void IndividualAggregator::doAddContact(const Result SYNCEVO_GLIB_CALL_ASYNC(folks_persona_store_add_persona_from_details, boost::bind(&IndividualAggregator::addContactDone, this, - _1, _2, + _2, _1, result), m_systemStore, details.get()); @@ -874,7 +874,7 @@ void IndividualAggregator::addContactDone(const GError *gerror, { try { // Handle result of folks_persona_store_add_persona_from_details(). - if (gerror) { + if (!gerror) { GErrorCXX::throwError("add contact", gerror); } diff --git a/src/syncevo/GLibSupport.h b/src/syncevo/GLibSupport.h index ac59d1c7..89925c61 100644 --- a/src/syncevo/GLibSupport.h +++ b/src/syncevo/GLibSupport.h @@ -41,6 +41,7 @@ typedef void *GMainLoop; #include #include #include +#include #include #include @@ -577,10 +578,172 @@ class PlainGStr : public boost::shared_ptr const gchar *c_str() const { return &**this; } }; -// non-void result, three parameters to finish function -template class GAsyncReadyCXX { - public: - typedef boost::function CXXFunctionCB_t; +// empty template, need specialization based on parameter and return types +template struct GAsyncReady5 {}; +template struct GAsyncReady4 {}; +template struct GAsyncReady3 {}; +template struct GAsyncReady2 {}; +template struct GAsyncReady1 {}; + +// empty template, need specializations based on arity +template struct GAsyncReadyCXX {}; + +// five parameters of finish function +template struct GAsyncReadyCXX : + public GAsyncReady5::result_type, + F, finish, + typename boost::function_traits::arg1_type, + typename boost::function_traits::arg2_type, + typename boost::function_traits::arg3_type, + typename boost::function_traits::arg4_type, + typename boost::function_traits::arg5_type> +{ +}; + +// four parameters +template struct GAsyncReadyCXX : + public GAsyncReady4::result_type, + F, finish, + typename boost::function_traits::arg1_type, + typename boost::function_traits::arg2_type, + typename boost::function_traits::arg3_type, + typename boost::function_traits::arg4_type> +{ +}; + +// three parameters +template struct GAsyncReadyCXX : + public GAsyncReady3::result_type, + F, finish, + typename boost::function_traits::arg1_type, + typename boost::function_traits::arg2_type, + typename boost::function_traits::arg3_type> +{ +}; + +// two parameters +template struct GAsyncReadyCXX : + public GAsyncReady2::result_type, + F, finish, + typename boost::function_traits::arg1_type, + typename boost::function_traits::arg2_type> +{ +}; + +// one parameter +template struct GAsyncReadyCXX : + public GAsyncReady1::result_type, + F, finish, + typename boost::function_traits::arg1_type> +{ +}; + + +// For finish functions with return parameters the assumption is that +// they have a non-void return value. Otherwise there would be no need +// for the return parameters. +// +// result = GObject, GAsyncResult, A3, A4, A5 +template struct GAsyncReady5 +{ + typedef typename boost::remove_pointer::type A3_t; + typedef typename boost::remove_pointer::type A4_t; + typedef typename boost::remove_pointer::type A5_t; + typedef boost::function CXXFunctionCB_t; + + static void handleGLibResult(GObject *sourceObject, + GAsyncResult *result, + gpointer userData) throw () { + try { + A3_t retval1 = boost::value_initialized(); + A4_t retval2 = boost::value_initialized(); + A5_t retval3 = boost::value_initialized(); + T t = finish(reinterpret_cast(sourceObject), + result, &retval1, &retval2, &retval3); + std::auto_ptr cb(static_cast(userData)); + (*cb)(t, retval1, retval2, retval3); + } catch (...) { + // called from C, must not let exception escape + Exception::handle(HANDLE_EXCEPTION_FATAL); + } + } +}; + +// result = GObject, GAsyncResult, A3, A4, GError +template struct GAsyncReady5 +{ + typedef typename boost::remove_pointer::type A3_t; + typedef typename boost::remove_pointer::type A4_t; + typedef boost::function CXXFunctionCB_t; + + static void handleGLibResult(GObject *sourceObject, + GAsyncResult *result, + gpointer userData) throw () { + try { + GErrorCXX gerror; + A3_t retval1 = boost::value_initialized(); + A4_t retval2 = boost::value_initialized(); + T t = finish(reinterpret_cast(sourceObject), + result, &retval1, &retval2, gerror); + std::auto_ptr cb(static_cast(userData)); + (*cb)(t, retval1, retval2, gerror); + } catch (...) { + // called from C, must not let exception escape + Exception::handle(HANDLE_EXCEPTION_FATAL); + } + } +}; + +// result = GObject, GAsyncResult, A3, A4 +template struct GAsyncReady4 +{ + typedef typename boost::remove_pointer::type A3_t; + typedef typename boost::remove_pointer::type A4_t; + typedef boost::function CXXFunctionCB_t; + + static void handleGLibResult(GObject *sourceObject, + GAsyncResult *result, + gpointer userData) throw () { + try { + A3_t retval1 = boost::value_initialized(); + A4_t retval2 = boost::value_initialized(); + T t = finish(reinterpret_cast(sourceObject), + result, &retval1, &retval2); + std::auto_ptr cb(static_cast(userData)); + (*cb)(t, retval1, retval2); + } catch (...) { + // called from C, must not let exception escape + Exception::handle(HANDLE_EXCEPTION_FATAL); + } + } +}; + +// result = GObject, GAsyncResult, A3, GError +template struct GAsyncReady4 +{ + typedef typename boost::remove_pointer::type A3_t; + typedef boost::function CXXFunctionCB_t; + + static void handleGLibResult(GObject *sourceObject, + GAsyncResult *result, + gpointer userData) throw () { + try { + GErrorCXX gerror; + A3_t retval = boost::value_initialized(); + T t = finish(reinterpret_cast(sourceObject), + result, &retval, gerror); + std::auto_ptr cb(static_cast(userData)); + (*cb)(t, retval, gerror); + } catch (...) { + // called from C, must not let exception escape + Exception::handle(HANDLE_EXCEPTION_FATAL); + } + } +}; + +// res = GObject, GAsyncResult, GError +template struct GAsyncReady3{ + typedef boost::function CXXFunctionCB_t; static void handleGLibResult(GObject *sourceObject, GAsyncResult *result, @@ -590,7 +753,7 @@ template class GAsyncReadyCXX { T t = finish(reinterpret_cast(sourceObject), result, gerror); std::auto_ptr cb(static_cast(userData)); - (*cb)(gerror, t); + (*cb)(t, gerror); } catch (...) { // called from C, must not let exception escape Exception::handle(HANDLE_EXCEPTION_FATAL); @@ -598,51 +761,9 @@ template class GAsyncReadyCXX { } }; -// non-void result type, two parameters for finish, -// first parameter is not GAsyncResult (= must be object pointer) -template class GAsyncReadyCXX { - public: - typedef boost::function CXXFunctionCB_t; - - static void handleGLibResult(GObject *sourceObject, - GAsyncResult *result, - gpointer userData) throw () { - try { - T t = finish(reinterpret_cast(sourceObject), - result); - std::auto_ptr cb(static_cast(userData)); - (*cb)(t); - } catch (...) { - // called from C, must not let exception escape - Exception::handle(HANDLE_EXCEPTION_FATAL); - } - } -}; - -// non-void result type, two parameters for finish, -// first parameter is GAsyncResult (= no object pointer) -template class GAsyncReadyCXX { - public: - typedef boost::function CXXFunctionCB_t; - - static void handleGLibResult(GObject *sourceObject, - GAsyncResult *result, - gpointer userData) throw () { - try { - GErrorCXX gerror; - T t = finish(result, gerror); - std::auto_ptr cb(static_cast(userData)); - (*cb)(gerror, t); - } catch (...) { - // called from C, must not let exception escape - Exception::handle(HANDLE_EXCEPTION_FATAL); - } - } -}; - -// void result type, three parameters of finish -template class GAsyncReadyCXX { - public: +// void = GObject, GAsyncResult, GError +template struct GAsyncReady3 +{ typedef boost::function CXXFunctionCB_t; static void handleGLibResult(GObject *sourceObject, @@ -661,10 +782,49 @@ template class GAsyncReadyCXX class GAsyncReadyCXX { +// result = GObject, GAsyncResult +template struct GAsyncReady2 +{ + typedef boost::function CXXFunctionCB_t; + + static void handleGLibResult(GObject *sourceObject, + GAsyncResult *result, + gpointer userData) throw () { + try { + T t = finish(reinterpret_cast(sourceObject), + result); + std::auto_ptr cb(static_cast(userData)); + (*cb)(t); + } catch (...) { + // called from C, must not let exception escape + Exception::handle(HANDLE_EXCEPTION_FATAL); + } + } +}; + +// result = GAsyncResult, GError +template struct GAsyncReady2 { public: + typedef boost::function CXXFunctionCB_t; + + static void handleGLibResult(GObject *sourceObject, + GAsyncResult *result, + gpointer userData) throw () { + try { + GErrorCXX gerror; + T t = finish(result, gerror); + std::auto_ptr cb(static_cast(userData)); + (*cb)(t, gerror); + } catch (...) { + // called from C, must not let exception escape + Exception::handle(HANDLE_EXCEPTION_FATAL); + } + } +}; + +// void = GObject, GAsyncResult +template struct GAsyncReady2 +{ typedef boost::function CXXFunctionCB_t; static void handleGLibResult(GObject *sourceObject, @@ -682,10 +842,9 @@ template class GAsyncReadyCXX class GAsyncReadyCXX { - public: +// void = GAsyncResult, GError +template struct GAsyncReady2 +{ typedef boost::function CXXFunctionCB_t; static void handleGLibResult(GObject *sourceObject, @@ -703,12 +862,13 @@ template class GAsyncReadyCXX::type>::result_type, \ - typeof(_prepare ## _finish) *, \ + GAsyncReadyCXX< boost::remove_pointer::type, \ & _prepare ## _finish, \ - boost::function_traits::type>::arg1_type, \ boost::function_traits::type>::arity > /** @@ -716,10 +876,16 @@ template class GAsyncReadyCXX class GAsyncReadyDoneCXX template static void storeResult(GErrorCXX &gerrorStorage, R &resultStorage, bool &done, - const GError *gerror, - T result) { + T result, + const GError *gerror) { done = true; gerrorStorage = gerror; resultStorage = result; } - template static boost::function createCB(R &result, GErrorCXX &gerror, bool &done) { + template static boost::function createCB(R &result, GErrorCXX &gerror, bool &done) { return boost::bind(storeResult, boost::ref(gerror), boost::ref(result), boost::ref(done), _1, _2); } };