From 091ee331a249a562bd4f1327a53e546c22964dbf Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 21 Jul 2017 19:12:30 +0100 Subject: [PATCH 1/2] Implement dbus_clear_connection(), etc. These are inspired by GLib's g_clear_pointer() and g_clear_object(), which in turn is descended from CPython's Py_CLEAR_OBJECT. They should make our code a lot less repetitive. Signed-off-by: Simon McVittie --- Be more careful with types and casts, to keep C++ compilers happy (see comment). This broke the build with mingw on Travis-CI, because we use a tiny amount of C++ on Windows to get code run at library init time in a non-horrific way. --- dbus/dbus-address.h | 19 +++++++++++++++++++ dbus/dbus-connection.h | 30 ++++++++++++++++++++++++++++++ dbus/dbus-hash.h | 6 ++++++ dbus/dbus-macros.h | 20 ++++++++++++++++++++ dbus/dbus-message-internal.h | 6 ++++++ dbus/dbus-message.h | 19 +++++++++++++++++++ dbus/dbus-pending-call.h | 19 +++++++++++++++++++ dbus/dbus-server.h | 19 +++++++++++++++++++ 8 files changed, 138 insertions(+) diff --git a/dbus/dbus-address.h b/dbus/dbus-address.h index 4d14fdf7..fefb320e 100644 --- a/dbus/dbus-address.h +++ b/dbus/dbus-address.h @@ -59,6 +59,25 @@ DBUS_EXPORT char* dbus_address_unescape_value (const char *value, DBusError *error); +/** + * Clear a variable or struct member that contains an array of #DBusAddressEntry. + * If it does not contain #NULL, the entries that were previously + * there are freed with dbus_address_entries_free(). + * + * This is similar to dbus_clear_connection(): see that function + * for more details. + * + * @param pointer_to_entries A pointer to a variable or struct member. + * pointer_to_entries must not be #NULL, but *pointer_to_entries + * may be #NULL. + */ +static inline void +dbus_clear_address_entries (DBusAddressEntry ***pointer_to_entries) +{ + _dbus_clear_pointer_impl (DBusAddressEntry *, pointer_to_entries, + dbus_address_entries_free); +} + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index fe4d04ef..bed54242 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -28,6 +28,7 @@ #define DBUS_CONNECTION_H #include +#include #include #include #include @@ -438,6 +439,35 @@ DBUS_EXPORT dbus_bool_t dbus_connection_get_socket (DBusConnection *connection, int *fd); +/** + * Clear a variable or struct member that contains a #DBusConnection. + * If it does not contain #NULL, the connection that was previously + * there is unreferenced with dbus_connection_unref(). + * + * For example, this function and the similar functions for + * other reference-counted types can be used in code like this: + * + * @code + * DBusConnection *conn = NULL; + * struct { ...; DBusMessage *m; ... } *larger_structure = ...; + * + * ... code that might set conn or m to be non-NULL ... + * + * dbus_clear_connection (&conn); + * dbus_clear_message (&larger_structure->m); + * @endcode + * + * @param pointer_to_connection A pointer to a variable or struct member. + * pointer_to_connection must not be #NULL, but *pointer_to_connection + * may be #NULL. + */ +static inline void +dbus_clear_connection (DBusConnection **pointer_to_connection) +{ + _dbus_clear_pointer_impl (DBusConnection, pointer_to_connection, + dbus_connection_unref); +} + /** @} */ diff --git a/dbus/dbus-hash.h b/dbus/dbus-hash.h index 93f717a9..fadab91f 100644 --- a/dbus/dbus-hash.h +++ b/dbus/dbus-hash.h @@ -210,6 +210,12 @@ _dbus_hash_table_insert_pollable (DBusHashTable *table, #endif } +static inline void +_dbus_clear_hash_table (DBusHashTable **table_p) +{ + _dbus_clear_pointer_impl (DBusHashTable, table_p, _dbus_hash_table_unref); +} + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-macros.h b/dbus/dbus-macros.h index 0e784fe1..2c8956e3 100644 --- a/dbus/dbus-macros.h +++ b/dbus/dbus-macros.h @@ -215,6 +215,26 @@ # define DBUS_PRIVATE_EXPORT /* no decoration */ #endif +/* Implementation for dbus_clear_message() etc. This is not API, + * do not use it directly. + * + * We're using a specific type (T ** and T *) instead of void ** and + * void * partly for type-safety, partly to be strict-aliasing-compliant, + * and partly to keep C++ compilers happy. This code is inlined into + * users of libdbus, so we can't rely on it having dbus' own compiler + * settings. */ +#define _dbus_clear_pointer_impl(T, pointer_to_pointer, destroy) \ + do { \ + T **_pp = (pointer_to_pointer); \ + T *_value = *_pp; \ + \ + *_pp = NULL; \ + \ + if (_value != NULL) \ + destroy (_value); \ + } while (0) +/* Not (destroy) (_value) in case destroy() is a function-like macro */ + /** @} */ #endif /* DBUS_MACROS_H */ diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h index f8fe383f..38c79236 100644 --- a/dbus/dbus-message-internal.h +++ b/dbus/dbus-message-internal.h @@ -135,6 +135,12 @@ const DBusString *_dbus_variant_peek (DBusVariant *s DBUS_PRIVATE_EXPORT const char *_dbus_variant_get_signature (DBusVariant *self); +static inline void +_dbus_clear_variant (DBusVariant **variant_p) +{ + _dbus_clear_pointer_impl (DBusVariant, variant_p, _dbus_variant_free); +} + typedef struct DBusInitialFDs DBusInitialFDs; DBusInitialFDs *_dbus_check_fdleaks_enter (void); void _dbus_check_fdleaks_leave (DBusInitialFDs *fds); diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 9e7ae7fe..8a9d57a0 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -351,6 +351,25 @@ DBUS_EXPORT dbus_bool_t dbus_message_get_allow_interactive_authorization ( DBusMessage *message); +/** + * Clear a variable or struct member that contains a #DBusMessage. + * If it does not contain #NULL, the message that was previously + * there is unreferenced with dbus_message_unref(). + * + * This is very similar to dbus_clear_connection(): see that function + * for more details. + * + * @param pointer_to_message A pointer to a variable or struct member. + * pointer_to_message must not be #NULL, but *pointer_to_message + * may be #NULL. + */ +static inline void +dbus_clear_message (DBusMessage **pointer_to_message) +{ + _dbus_clear_pointer_impl (DBusMessage, pointer_to_message, + dbus_message_unref); +} + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-pending-call.h b/dbus/dbus-pending-call.h index 8a37ec0a..5593397a 100644 --- a/dbus/dbus-pending-call.h +++ b/dbus/dbus-pending-call.h @@ -72,6 +72,25 @@ DBUS_EXPORT void* dbus_pending_call_get_data (DBusPendingCall *pending, dbus_int32_t slot); +/** + * Clear a variable or struct member that contains a #DBusPendingCall. + * If it does not contain #NULL, the pending call that was previously + * there is unreferenced with dbus_pending_call_unref(). + * + * This is very similar to dbus_clear_connection(): see that function + * for more details. + * + * @param pointer_to_pending_call A pointer to a variable or struct member. + * pointer_to_pending_call must not be #NULL, but *pointer_to_pending_call + * may be #NULL. + */ +static inline void +dbus_clear_pending_call (DBusPendingCall **pointer_to_pending_call) +{ + _dbus_clear_pointer_impl (DBusPendingCall, pointer_to_pending_call, + dbus_pending_call_unref); +} + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h index bdbefa0f..7d8f04e4 100644 --- a/dbus/dbus-server.h +++ b/dbus/dbus-server.h @@ -28,6 +28,7 @@ #define DBUS_SERVER_H #include +#include #include #include #include @@ -99,6 +100,24 @@ DBUS_EXPORT void* dbus_server_get_data (DBusServer *server, int slot); +/** + * Clear a variable or struct member that contains a #DBusServer. + * If it does not contain #NULL, the server that was previously + * there is unreferenced with dbus_server_unref(). + * + * This is very similar to dbus_clear_connection(): see that function + * for more details. + * + * @param pointer_to_server A pointer to a variable or struct member. + * pointer_to_server must not be #NULL, but *pointer_to_server + * may be #NULL. + */ +static inline void +dbus_clear_server (DBusServer **pointer_to_server) +{ + _dbus_clear_pointer_impl (DBusServer, pointer_to_server, dbus_server_unref); +} + /** @} */ DBUS_END_DECLS -- 2.13.3