From 44b7876133fcaa81f71462f8058d5d3450a2548c Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 27 Apr 2012 15:02:07 +0100 Subject: [PATCH 1/6] Move some TpProxy functionality into the -core library Most of this just calls into a vtable set up by the -main library, but it's enough for the generated code not to have an explicit (circular) dependency on the -main library. --- telepathy-glib/Makefile.am | 1 + telepathy-glib/core-proxy.c | 174 +++++++++++++++++++++++++++++++++++++++ telepathy-glib/proxy-internal.h | 91 ++++++++++++++++++++ telepathy-glib/proxy-methods.c | 44 ++++++---- telepathy-glib/proxy-signals.c | 35 ++++---- telepathy-glib/proxy.c | 72 ++++++---------- 6 files changed, 338 insertions(+), 79 deletions(-) create mode 100644 telepathy-glib/core-proxy.c diff --git a/telepathy-glib/Makefile.am b/telepathy-glib/Makefile.am index 83e7613..8042cc9 100644 --- a/telepathy-glib/Makefile.am +++ b/telepathy-glib/Makefile.am @@ -173,6 +173,7 @@ check-local: check-coding-style libtelepathy_glib_core_internal_la_LIBADD = $(ALL_LIBS) libtelepathy_glib_core_internal_la_SOURCES = \ core-dbus.c \ + core-proxy.c \ errors.c \ $(NULL) diff --git a/telepathy-glib/core-proxy.c b/telepathy-glib/core-proxy.c new file mode 100644 index 0000000..427785a --- /dev/null +++ b/telepathy-glib/core-proxy.c @@ -0,0 +1,174 @@ +/* + * core-proxy.c - parts of TpProxy needed to link generated code + * + * Copyright © 2007-2012 Collabora Ltd. + * Copyright © 2007-2008 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "telepathy-glib/proxy-subclass.h" +#include "telepathy-glib/proxy-internal.h" + +#include + +#define DEBUG_FLAG TP_DEBUG_PROXY +#include "debug-internal.h" + +/** + * tp_proxy_dbus_g_proxy_claim_for_signal_adding: + * @proxy: a #DBusGProxy + * + * Attempt to "claim" a #DBusGProxy for addition of signal signatures. + * If this function has not been called on @proxy before, %TRUE is + * returned, and the caller may safely call dbus_g_proxy_add_signal() + * on @proxy. If this function has already been caled, %FALSE is + * returned, and the caller may not safely call dbus_g_proxy_add_signal(). + * + * This is intended for use by auto-generated signal-adding functions, + * to allow interfaces provided as local extensions to override those in + * telepathy-glib without causing assertion failures. + * + * Returns: %TRUE if it is safe to call dbus_g_proxy_add_signal() + * Since: 0.7.6 + */ +gboolean +tp_proxy_dbus_g_proxy_claim_for_signal_adding (DBusGProxy *proxy) +{ + static GQuark q = 0; + + g_return_val_if_fail (proxy != NULL, FALSE); + + if (G_UNLIKELY (q == 0)) + { + q = g_quark_from_static_string ( + "tp_proxy_dbus_g_proxy_claim_for_signal_adding@0.7.6"); + } + + if (g_object_get_qdata ((GObject *) proxy, q) != NULL) + { + /* Someone else has already added signal signatures for this interface. + * We can't do it again or it'll cause an assertion */ + return FALSE; + } + + /* the proxy is just used as qdata here because it's a convenient + * non-NULL pointer */ + g_object_set_qdata ((GObject *) proxy, q, proxy); + return TRUE; +} + +static TpProxyImplementation _tp_proxy_implementation = { NULL }; + +DBusGProxy * +tp_proxy_borrow_interface_by_id (TpProxy *proxy, + GQuark iface, + GError **error) +{ + g_assert (_tp_proxy_implementation.version != NULL); + return _tp_proxy_implementation.borrow_interface_by_id (proxy, iface, error); +} + +TpProxyPendingCall * +tp_proxy_pending_call_v0_new (TpProxy *proxy, + GQuark iface, + const gchar *member, + DBusGProxy *iface_proxy, + TpProxyInvokeFunc invoke_callback, + GCallback callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object, + gboolean cancel_must_raise) +{ + g_assert (_tp_proxy_implementation.version != NULL); + return _tp_proxy_implementation.pending_call_new (proxy, iface, member, + iface_proxy, invoke_callback, callback, user_data, destroy, + weak_object, cancel_must_raise); +} + +void +tp_proxy_pending_call_v0_take_pending_call (TpProxyPendingCall *pc, + DBusGProxyCall *pending_call) +{ + g_assert (_tp_proxy_implementation.version != NULL); + _tp_proxy_implementation.pending_call_take_pending_call (pc, pending_call); +} + +void +tp_proxy_pending_call_v0_completed (gpointer p) +{ + g_assert (_tp_proxy_implementation.version != NULL); + _tp_proxy_implementation.pending_call_completed (p); +} + +void +tp_proxy_pending_call_v0_take_results (TpProxyPendingCall *pc, + GError *error, + GValueArray *args) +{ + g_assert (_tp_proxy_implementation.version != NULL); + _tp_proxy_implementation.pending_call_take_results (pc, error, args); +} + +TpProxySignalConnection * +tp_proxy_signal_connection_v0_new (TpProxy *self, + GQuark iface, + const gchar *member, + const GType *expected_types, + GCallback collect_args, + TpProxyInvokeFunc invoke_callback, + GCallback callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object, + GError **error) +{ + g_assert (_tp_proxy_implementation.version != NULL); + return _tp_proxy_implementation.signal_connection_new (self, iface, member, + expected_types, collect_args, invoke_callback, callback, user_data, + destroy, weak_object, error); +} + +void +tp_proxy_signal_connection_v0_take_results (TpProxySignalConnection *sc, + GValueArray *args) +{ + g_assert (_tp_proxy_implementation.version != NULL); + _tp_proxy_implementation.signal_connection_take_results (sc, args); +} + +void +tp_private_proxy_set_implementation (TpProxyImplementation *impl) +{ + g_assert_cmpstr (impl->version, ==, VERSION); + g_assert_cmpuint (impl->size, ==, sizeof (TpProxyImplementation)); + g_assert_cmpstr (g_type_name (impl->type), ==, "TpProxy"); + g_assert (_tp_proxy_implementation.version == NULL); + + g_assert (impl->borrow_interface_by_id != NULL); + g_assert (impl->pending_call_new != NULL); + g_assert (impl->pending_call_take_pending_call != NULL); + g_assert (impl->pending_call_take_results != NULL); + g_assert (impl->pending_call_completed != NULL); + g_assert (impl->signal_connection_new != NULL); + g_assert (impl->signal_connection_take_results != NULL); + + memcpy (&_tp_proxy_implementation, impl, sizeof (TpProxyImplementation)); + + g_assert_cmpstr (_tp_proxy_implementation.version, ==, VERSION); +} diff --git a/telepathy-glib/proxy-internal.h b/telepathy-glib/proxy-internal.h index a01d021..735b21f 100644 --- a/telepathy-glib/proxy-internal.h +++ b/telepathy-glib/proxy-internal.h @@ -21,6 +21,97 @@ #define __TP_PROXY_INTERNAL_H__ #include +#include + +typedef struct { + const gchar *version; + gsize size; + + DBusGProxy *(*borrow_interface_by_id) (TpProxy *, + GQuark, + GError **); + + TpProxyPendingCall *(*pending_call_new) (TpProxy *, + GQuark, + const gchar *, + DBusGProxy *, + TpProxyInvokeFunc, + GCallback, + gpointer, + GDestroyNotify, + GObject *, + gboolean); + void (*pending_call_take_pending_call) (TpProxyPendingCall *, + DBusGProxyCall *); + void (*pending_call_take_results) (TpProxyPendingCall *, + GError *, + GValueArray *); + GDestroyNotify pending_call_completed; + + TpProxySignalConnection *(*signal_connection_new) (TpProxy *, + GQuark, + const gchar *, + const GType *, + GCallback, + TpProxyInvokeFunc, + GCallback, + gpointer, + GDestroyNotify, + GObject *, + GError **); + void (*signal_connection_take_results) (TpProxySignalConnection *, + GValueArray *); + + GType type; +} TpProxyImplementation; + +DBusGProxy *_tp_proxy_borrow_interface_by_id (TpProxy *self, + GQuark iface, + GError **error); + +TpProxyPendingCall *_tp_proxy_pending_call_new (TpProxy *self, + GQuark iface, + const gchar *member, + DBusGProxy *iface_proxy, + TpProxyInvokeFunc invoke_callback, + GCallback callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object, + gboolean cancel_must_raise); + +void _tp_proxy_pending_call_take_pending_call (TpProxyPendingCall *pc, + DBusGProxyCall *pending_call); + +void _tp_proxy_pending_call_take_results (TpProxyPendingCall *pc, + GError *error, + GValueArray *args); + +void _tp_proxy_pending_call_completed (gpointer p); + +TpProxySignalConnection *_tp_proxy_signal_connection_new (TpProxy *self, + GQuark iface, + const gchar *member, + const GType *expected_types, + GCallback collect_args, + TpProxyInvokeFunc invoke_callback, + GCallback callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object, + GError **error); + +void _tp_proxy_signal_connection_take_results (TpProxySignalConnection *sc, + GValueArray *args); + +/* + * Implemented in the -core library, and called by the -main library. + * + * This is only extern so that the -main part can call into the + * -core part across a shared-library boundary. If you are not + * TpProxy early initialization, don't. + */ +void tp_private_proxy_set_implementation (TpProxyImplementation *impl); GError *_tp_proxy_take_and_remap_error (TpProxy *self, GError *error) G_GNUC_WARN_UNUSED_RESULT; diff --git a/telepathy-glib/proxy-methods.c b/telepathy-glib/proxy-methods.c index 8c56ebf..de0f796 100644 --- a/telepathy-glib/proxy-methods.c +++ b/telepathy-glib/proxy-methods.c @@ -242,17 +242,20 @@ _tp_proxy_pending_call_dgproxy_destroy (DBusGProxy *iface_proxy, * * Since: 0.7.1 */ + +/* that's implemented in the core library, but it calls this: */ + TpProxyPendingCall * -tp_proxy_pending_call_v0_new (TpProxy *self, - GQuark iface, - const gchar *member, - DBusGProxy *iface_proxy, - TpProxyInvokeFunc invoke_callback, - GCallback callback, - gpointer user_data, - GDestroyNotify destroy, - GObject *weak_object, - gboolean cancel_must_raise) +_tp_proxy_pending_call_new (TpProxy *self, + GQuark iface, + const gchar *member, + DBusGProxy *iface_proxy, + TpProxyInvokeFunc invoke_callback, + GCallback callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object, + gboolean cancel_must_raise) { TpProxyPendingCall *pc; @@ -408,8 +411,11 @@ tp_proxy_pending_call_free (TpProxyPendingCall *pc) * * Since: 0.7.1 */ + +/* that's implemented in the core library, but it calls this: */ + void -tp_proxy_pending_call_v0_completed (gpointer p) +_tp_proxy_pending_call_completed (gpointer p) { TpProxyPendingCall *pc = p; @@ -455,9 +461,12 @@ tp_proxy_pending_call_v0_completed (gpointer p) * * Since: 0.7.1 */ + +/* that's implemented in the core library, but it calls this: */ + void -tp_proxy_pending_call_v0_take_pending_call (TpProxyPendingCall *pc, - DBusGProxyCall *pending_call) +_tp_proxy_pending_call_take_pending_call (TpProxyPendingCall *pc, + DBusGProxyCall *pending_call) { g_return_if_fail (pc->priv == pending_call_magic); g_return_if_fail (pc->pending_call == NULL); @@ -499,10 +508,13 @@ _tp_proxy_pending_call_idle_completed (gpointer p) * * Since: 0.7.1 */ + +/* that's implemented in the core library, but it calls this: */ + void -tp_proxy_pending_call_v0_take_results (TpProxyPendingCall *pc, - GError *error, - GValueArray *args) +_tp_proxy_pending_call_take_results (TpProxyPendingCall *pc, + GError *error, + GValueArray *args) { g_return_if_fail (pc->proxy != NULL); g_return_if_fail (pc->priv == pending_call_magic); diff --git a/telepathy-glib/proxy-signals.c b/telepathy-glib/proxy-signals.c index 013faf4..e5629f1 100644 --- a/telepathy-glib/proxy-signals.c +++ b/telepathy-glib/proxy-signals.c @@ -20,6 +20,7 @@ #include "config.h" #include "telepathy-glib/proxy-subclass.h" +#include "telepathy-glib/proxy-internal.h" #define DEBUG_FLAG TP_DEBUG_PROXY #include "telepathy-glib/debug-internal.h" @@ -314,7 +315,7 @@ _tp_proxy_signal_connection_dgproxy_destroy (DBusGProxy *iface_proxy, static void collect_none (DBusGProxy *dgproxy, TpProxySignalConnection *sc) { - tp_proxy_signal_connection_v0_take_results (sc, NULL); + _tp_proxy_signal_connection_take_results (sc, NULL); } /** @@ -356,18 +357,21 @@ collect_none (DBusGProxy *dgproxy, TpProxySignalConnection *sc) * * Since: 0.7.1 */ + +/* that's implemented in the core library, but it calls this: */ + TpProxySignalConnection * -tp_proxy_signal_connection_v0_new (TpProxy *self, - GQuark iface, - const gchar *member, - const GType *expected_types, - GCallback collect_args, - TpProxyInvokeFunc invoke_callback, - GCallback callback, - gpointer user_data, - GDestroyNotify destroy, - GObject *weak_object, - GError **error) +_tp_proxy_signal_connection_new (TpProxy *self, + GQuark iface, + const gchar *member, + const GType *expected_types, + GCallback collect_args, + TpProxyInvokeFunc invoke_callback, + GCallback callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object, + GError **error) { TpProxySignalConnection *sc; DBusGProxy *iface_proxy = tp_proxy_borrow_interface_by_id (self, @@ -437,9 +441,12 @@ tp_proxy_signal_connection_v0_new (TpProxy *self, * * Since: 0.7.1 */ + +/* that's implemented in the core library, but it calls this: */ + void -tp_proxy_signal_connection_v0_take_results (TpProxySignalConnection *sc, - GValueArray *args) +_tp_proxy_signal_connection_take_results (TpProxySignalConnection *sc, + GValueArray *args) { TpProxySignalInvocation *invocation = g_slice_new0 (TpProxySignalInvocation); /* FIXME: assert that the GValueArray is the right length, or diff --git a/telepathy-glib/proxy.c b/telepathy-glib/proxy.c index c9097dd..26cad31 100644 --- a/telepathy-glib/proxy.c +++ b/telepathy-glib/proxy.c @@ -419,10 +419,13 @@ static void tp_proxy_iface_destroyed_cb (DBusGProxy *dgproxy, TpProxy *self); * * Since: 0.7.1 */ + +/* that's implemented in the core library, but it calls this: */ + DBusGProxy * -tp_proxy_borrow_interface_by_id (TpProxy *self, - GQuark iface, - GError **error) +_tp_proxy_borrow_interface_by_id (TpProxy *self, + GQuark iface, + GError **error) { gpointer dgproxy; @@ -1511,55 +1514,26 @@ tp_proxy_get_invalidated (gpointer self) return proxy->invalidated; } -/** - * tp_proxy_dbus_g_proxy_claim_for_signal_adding: - * @proxy: a #DBusGProxy - * - * Attempt to "claim" a #DBusGProxy for addition of signal signatures. - * If this function has not been called on @proxy before, %TRUE is - * returned, and the caller may safely call dbus_g_proxy_add_signal() - * on @proxy. If this function has already been caled, %FALSE is - * returned, and the caller may not safely call dbus_g_proxy_add_signal(). - * - * This is intended for use by auto-generated signal-adding functions, - * to allow interfaces provided as local extensions to override those in - * telepathy-glib without causing assertion failures. - * - * Returns: %TRUE if it is safe to call dbus_g_proxy_add_signal() - * Since: 0.7.6 - */ -gboolean -tp_proxy_dbus_g_proxy_claim_for_signal_adding (DBusGProxy *proxy) -{ - static GQuark q = 0; - - g_return_val_if_fail (proxy != NULL, FALSE); - - if (G_UNLIKELY (q == 0)) - { - q = g_quark_from_static_string ( - "tp_proxy_dbus_g_proxy_claim_for_signal_adding@0.7.6"); - } - - if (g_object_get_qdata ((GObject *) proxy, q) != NULL) - { - /* Someone else has already added signal signatures for this interface. - * We can't do it again or it'll cause an assertion */ - return FALSE; - } - - /* the proxy is just used as qdata here because it's a convenient - * non-NULL pointer */ - g_object_set_qdata ((GObject *) proxy, q, proxy); - return TRUE; -} - static gpointer tp_proxy_once (gpointer data G_GNUC_UNUSED) { - GType type = TP_TYPE_PROXY; - - tp_proxy_or_subclass_hook_on_interface_add (type, + TpProxyImplementation impl = { + VERSION, + sizeof (TpProxyImplementation), + _tp_proxy_borrow_interface_by_id, + _tp_proxy_pending_call_new, + _tp_proxy_pending_call_take_pending_call, + _tp_proxy_pending_call_take_results, + _tp_proxy_pending_call_completed, + _tp_proxy_signal_connection_new, + _tp_proxy_signal_connection_take_results, + /* keep this at the end as a final sanity-check of the size */ + TP_TYPE_PROXY + }; + + tp_private_proxy_set_implementation (&impl); + + tp_proxy_or_subclass_hook_on_interface_add (impl.type, tp_cli_generic_add_signals); return NULL; -- 1.7.10