GncGSettings - rework signal handler manipulation

Use ref-counting to manage GSettings object lifecycle
Use g_signal_handler_handlers_[un]block_matched to
block or unblock handlers rather than tracking them in
our own hash table.
This commit is contained in:
Geert Janssens 2023-02-17 11:43:25 +01:00
parent 4761aa414c
commit 03aff5642a
2 changed files with 59 additions and 97 deletions

View File

@ -49,8 +49,6 @@ namespace bpt = boost::property_tree;
static GHashTable *schema_hash = nullptr; static GHashTable *schema_hash = nullptr;
static GHashTable *registered_handlers_hash = nullptr;
/* This static indicates the debugging module that this .o belongs to. */ /* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = "gnc.app-utils.gsettings"; static QofLogModule log_module = "gnc.app-utils.gsettings";
@ -104,20 +102,6 @@ static GSettings * gnc_gsettings_get_settings_obj (const gchar *schema_str)
return gset; return gset;
} }
static void
handlers_hash_block_helper (gpointer key, gpointer gs_obj, [[maybe_unused]] gpointer pointer)
{
g_signal_handler_block (gs_obj, (gulong)key); // block signal_handler
PINFO("Block handler_id %ld for gs_obj %p", (gulong)key, gs_obj);
}
static void
handlers_hash_unblock_helper (gpointer key, gpointer gs_obj, [[maybe_unused]] gpointer pointer)
{
g_signal_handler_unblock (gs_obj, (gulong)key); // unblock signal_handler
PINFO("UnBlock handler_id %ld for gs_obj %p", (gulong)key, gs_obj);
}
/************************************************************/ /************************************************************/
/* GSettings Utilities */ /* GSettings Utilities */
/************************************************************/ /************************************************************/
@ -147,19 +131,15 @@ gnc_gsettings_normalize_schema_name (const gchar *name)
/************************************************************/ /************************************************************/
gulong gulong
gnc_gsettings_register_cb (const gchar *schema, gnc_gsettings_register_cb (const gchar *schema, const gchar *key,
const gchar *key,
gpointer func, gpointer func,
gpointer user_data) gpointer user_data)
{ {
ENTER(""); ENTER("");
g_return_val_if_fail (func, 0); g_return_val_if_fail (func, 0);
if (!schema_hash) if (!schema_hash)
schema_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nullptr); schema_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
if (!registered_handlers_hash)
registered_handlers_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
auto full_name = gnc_gsettings_normalize_schema_name (schema); auto full_name = gnc_gsettings_normalize_schema_name (schema);
auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name)); auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
@ -182,7 +162,7 @@ gnc_gsettings_register_cb (const gchar *schema,
auto handlerid = g_signal_connect (gs_obj, signal, G_CALLBACK (func), user_data); auto handlerid = g_signal_connect (gs_obj, signal, G_CALLBACK (func), user_data);
if (handlerid) if (handlerid)
{ {
g_hash_table_insert (registered_handlers_hash, GINT_TO_POINTER(handlerid), gs_obj); g_object_ref (gs_obj);
PINFO("schema: %s, key: %s, gs_obj: %p, handler_id: %ld", PINFO("schema: %s, key: %s, gs_obj: %p, handler_id: %ld",
schema, key, gs_obj, handlerid); schema, key, gs_obj, handlerid);
@ -195,42 +175,22 @@ gnc_gsettings_register_cb (const gchar *schema,
static void static void
gnc_gsettings_remove_cb_by_id_internal (GSettings *gs_obj, gnc_gsettings_remove_cb_by_id_internal (GSettings *gs_obj, guint handlerid)
guint handlerid)
{ {
ENTER (); ENTER ();
g_return_if_fail (G_IS_SETTINGS (gs_obj)); g_return_if_fail (G_IS_SETTINGS (gs_obj));
g_signal_handler_disconnect (gs_obj, handlerid); g_signal_handler_disconnect (gs_obj, handlerid);
g_object_unref (gs_obj);
// remove the handlerid from the registerered_handlers_hash LEAVE ("Schema: %p, handlerid: %d - removed for handler",
g_hash_table_remove (registered_handlers_hash, GINT_TO_POINTER(handlerid)); gs_obj, handlerid);
// remove GSettings object if we're not using it any more for other handlers
auto used_settings_objs = g_hash_table_get_values (registered_handlers_hash);
if (!g_list_find (used_settings_objs, gs_obj))
{
g_hash_table_remove(schema_hash, gs_obj);
g_object_unref (gs_obj);
}
// destroy hash table if size is 0
if (g_hash_table_size (registered_handlers_hash) == 0)
{
g_hash_table_destroy (registered_handlers_hash);
PINFO ("All registered preference callbacks removed");
}
LEAVE ("Schema: %p, handlerid: %d, hashtable size: %d - removed for handler",
gs_obj, handlerid, g_hash_table_size (registered_handlers_hash));
} }
void void
gnc_gsettings_remove_cb_by_func (const gchar *schema, gnc_gsettings_remove_cb_by_func (const gchar *schema, const gchar *key,
const gchar *key, gpointer func, gpointer user_data)
gpointer func,
gpointer user_data)
{ {
ENTER (); ENTER ();
g_return_if_fail (func); g_return_if_fail (func);
@ -267,14 +227,13 @@ gnc_gsettings_remove_cb_by_func (const gchar *schema,
} }
} while (handler_id); } while (handler_id);
LEAVE ("Schema: %s, key: %s, hashtable size: %d - removed %d handlers for 'changed' signal", LEAVE ("Schema: %s, key: %s - removed %d handlers for 'changed' signal",
schema, key, g_hash_table_size (registered_handlers_hash), matched); schema, key, matched);
} }
void void
gnc_gsettings_remove_cb_by_id (const gchar *schema, gnc_gsettings_remove_cb_by_id (const gchar *schema, guint handlerid)
guint handlerid)
{ {
ENTER (); ENTER ();
@ -290,8 +249,8 @@ gnc_gsettings_remove_cb_by_id (const gchar *schema,
gnc_gsettings_remove_cb_by_id_internal (gs_obj, handlerid); gnc_gsettings_remove_cb_by_id_internal (gs_obj, handlerid);
LEAVE ("Schema: %p, handlerid: %d, hashtable size: %d - removed for handler", LEAVE ("Schema: %p, handlerid: %d - removed for handler",
gs_obj, handlerid, g_hash_table_size (registered_handlers_hash)); gs_obj, handlerid);
} }
@ -327,6 +286,39 @@ void gnc_gsettings_bind (const gchar *schema,
PERR ("Invalid key %s for schema %s", key, schema); PERR ("Invalid key %s for schema %s", key, schema);
} }
static void
gs_obj_block_handlers ([[maybe_unused]] gpointer key, gpointer gs_obj,
[[maybe_unused]] gpointer pointer)
{
g_signal_handlers_block_matched (gs_obj, G_SIGNAL_MATCH_CLOSURE, 0, 0, NULL, NULL, NULL);
PINFO("Block all handlers for GSettings object %p", gs_obj);
}
static void
gs_obj_unblock_handlers ([[maybe_unused]] gpointer key, gpointer gs_obj,
[[maybe_unused]] gpointer pointer)
{
g_signal_handlers_unblock_matched (gs_obj, G_SIGNAL_MATCH_CLOSURE, 0, 0, NULL, NULL, NULL);
PINFO("Unblock all handlers for GSettings object %p", gs_obj);
}
void gnc_gsettings_block_all (void)
{
ENTER ();
g_hash_table_foreach (schema_hash, gs_obj_block_handlers, nullptr);
LEAVE();
}
void gnc_gsettings_unblock_all (void)
{
ENTER ();
g_hash_table_foreach (schema_hash, gs_obj_unblock_handlers, nullptr);
LEAVE();
}
/************************************************************/ /************************************************************/
/* Getters */ /* Getters */
/************************************************************/ /************************************************************/
@ -774,21 +766,3 @@ void gnc_gsettings_version_upgrade (void)
LEAVE(""); LEAVE("");
} }
void gnc_gsettings_block_all (void)
{
PINFO("block registered_handlers_hash list size is %d",
g_hash_table_size (registered_handlers_hash));
g_hash_table_foreach (registered_handlers_hash,
handlers_hash_block_helper, nullptr);
}
void gnc_gsettings_unblock_all (void)
{
PINFO("unblock registered_handlers_hash list size is %d",
g_hash_table_size (registered_handlers_hash));
g_hash_table_foreach (registered_handlers_hash,
handlers_hash_unblock_helper, nullptr);
}

View File

@ -278,8 +278,7 @@ gboolean gnc_gsettings_get_bool (const gchar *schema,
* processing, this function passed on the value of zero as returned * processing, this function passed on the value of zero as returned
* by GSettings. * by GSettings.
*/ */
gint gnc_gsettings_get_int (const gchar *schema, gint gnc_gsettings_get_int (const gchar *schema, const gchar *key);
const gchar *key);
/** Get an float value from GSettings. /** Get an float value from GSettings.
* *
@ -304,8 +303,7 @@ gint gnc_gsettings_get_int (const gchar *schema,
* processing, this function passed on the value of zero as returned * processing, this function passed on the value of zero as returned
* by GSettings. * by GSettings.
*/ */
gdouble gnc_gsettings_get_float (const gchar *schema, gdouble gnc_gsettings_get_float (const gchar *schema, const gchar *key);
const gchar *key);
/** Get a string value from GSettings. /** Get a string value from GSettings.
* *
@ -331,8 +329,7 @@ gdouble gnc_gsettings_get_float (const gchar *schema,
* GSettings. It is the callers responsibility to free any string * GSettings. It is the callers responsibility to free any string
* returned by this function. * returned by this function.
*/ */
gchar *gnc_gsettings_get_string (const gchar *schema, gchar *gnc_gsettings_get_string (const gchar *schema, const gchar *key);
const gchar *key);
/** Get an enum value from GSettings. /** Get an enum value from GSettings.
* *
@ -357,8 +354,7 @@ gchar *gnc_gsettings_get_string (const gchar *schema,
* processing, this function passed on the value of zero as returned * processing, this function passed on the value of zero as returned
* by GSettings. * by GSettings.
*/ */
gint gnc_gsettings_get_enum (const gchar *schema, gint gnc_gsettings_get_enum (const gchar *schema, const gchar *key);
const gchar *key);
/** Get an arbitrary combination of values from GSettings. /** Get an arbitrary combination of values from GSettings.
* *
@ -387,8 +383,7 @@ gint gnc_gsettings_get_enum (const gchar *schema,
* It is the callers responsibility to free any GVariant data returned * It is the callers responsibility to free any GVariant data returned
* by this function. * by this function.
*/ */
GVariant *gnc_gsettings_get_value (const gchar *schema, GVariant *gnc_gsettings_get_value (const gchar *schema, const gchar *key);
const gchar *key);
/** @} */ /** @} */
@ -418,8 +413,7 @@ GVariant *gnc_gsettings_get_value (const gchar *schema,
* @return This function returns true if the value was set successfully * @return This function returns true if the value was set successfully
* on the key or false if not. * on the key or false if not.
*/ */
gboolean gnc_gsettings_set_bool (const gchar *schema, gboolean gnc_gsettings_set_bool (const gchar *schema, const gchar *key,
const gchar *key,
gboolean value); gboolean value);
/** Store an integer value into GSettings. /** Store an integer value into GSettings.
@ -443,8 +437,7 @@ gboolean gnc_gsettings_set_bool (const gchar *schema,
* @return This function returns true if the value was set successfully * @return This function returns true if the value was set successfully
* on the key or false if not. * on the key or false if not.
*/ */
gboolean gnc_gsettings_set_int (const gchar *schema, gboolean gnc_gsettings_set_int (const gchar *schema, const gchar *key,
const gchar *key,
gint value); gint value);
/** Store a float value into GSettings. /** Store a float value into GSettings.
@ -468,8 +461,7 @@ gboolean gnc_gsettings_set_int (const gchar *schema,
* @return This function returns true if the value was set successfully * @return This function returns true if the value was set successfully
* on the key or false if not. * on the key or false if not.
*/ */
gboolean gnc_gsettings_set_float (const gchar *schema, gboolean gnc_gsettings_set_float (const gchar *schema, const gchar *key,
const gchar *key,
gdouble value); gdouble value);
@ -496,8 +488,7 @@ gboolean gnc_gsettings_set_float (const gchar *schema,
* @return This function returns true if the value was set successfully * @return This function returns true if the value was set successfully
* on the key or false if not. * on the key or false if not.
*/ */
gboolean gnc_gsettings_set_string (const gchar *schema, gboolean gnc_gsettings_set_string (const gchar *schema, const gchar *key,
const gchar *key,
const gchar *value); const gchar *value);
/** Store an enum value into GSettings. /** Store an enum value into GSettings.
@ -521,8 +512,7 @@ gboolean gnc_gsettings_set_string (const gchar *schema,
* @return This function returns true if the value was set successfully * @return This function returns true if the value was set successfully
* on the key or false if not. * on the key or false if not.
*/ */
gboolean gnc_gsettings_set_enum (const gchar *schema, gboolean gnc_gsettings_set_enum (const gchar *schema, const gchar *key,
const gchar *key,
gint value); gint value);
/** Store an arbitrary combination of values into GSettings. /** Store an arbitrary combination of values into GSettings.
@ -549,8 +539,7 @@ gboolean gnc_gsettings_set_enum (const gchar *schema,
* @return This function returns true if the value was set successfully * @return This function returns true if the value was set successfully
* on the key or false if not. * on the key or false if not.
*/ */
gboolean gnc_gsettings_set_value (const gchar *schema, gboolean gnc_gsettings_set_value (const gchar *schema, const gchar *key,
const gchar *key,
GVariant *value); GVariant *value);
/** Reset a key to its default value in GSettings. /** Reset a key to its default value in GSettings.
@ -572,8 +561,7 @@ gboolean gnc_gsettings_set_value (const gchar *schema,
* @param key This string is the name of the particular key within * @param key This string is the name of the particular key within
* the named schema of gsettings. * the named schema of gsettings.
*/ */
void gnc_gsettings_reset (const gchar *schema, void gnc_gsettings_reset (const gchar *schema, const gchar *key);
const gchar *key);
/** Reset all keys in a schema to their default values in GSettings. /** Reset all keys in a schema to their default values in GSettings.
* *