Mercurial > pidgin
changeset 26520:0cbdc2639ce2
Add purple_{buddy,chat,group,contact}_destroy to the blist API, free
blist data on libpurple unload. Thanks to Nick Hebner for this.
References #8683
committer: Ethan Blanton <elb@pidgin.im>
author | Nick Hebner <hebnern@gmail.com> |
---|---|
date | Thu, 09 Apr 2009 17:33:20 +0000 |
parents | 00f13da82914 |
children | 6b0c6a370cda |
files | ChangeLog ChangeLog.API libpurple/blist.c libpurple/blist.h |
diffstat | 4 files changed, 132 insertions(+), 43 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu Apr 09 01:59:24 2009 +0000 +++ b/ChangeLog Thu Apr 09 17:33:20 2009 +0000 @@ -9,6 +9,9 @@ * Removed the unmaintained and unneeded toc protocol plugin. * Fixed NTLM authentication on big-endian systems. + libpurple: + * Various memory cleanups when unloading libpurple. (Nick Hebner) + XMPP: * Add voice & video support with Jingle (XEP-0166, 0167, 0176, & 0177), and voice support with GTalk and GMail. (Mike "Maiku" Ruprecht)
--- a/ChangeLog.API Thu Apr 09 01:59:24 2009 +0000 +++ b/ChangeLog.API Thu Apr 09 17:33:20 2009 +0000 @@ -9,6 +9,7 @@ * PURPLE_CONTACT * PURPLE_BUDDY * PURPLE_CHAT + * purple_buddy_destroy * purple_buddy_get_protocol_data * purple_buddy_set_protocol_data * purple_buddy_get_local_buddy_alias @@ -17,9 +18,12 @@ * purple_blist_set_ui_data * purple_blist_node_get_ui_data * purple_blist_node_set_ui_data + * purple_chat_destroy * purple_connection_get_protocol_data * purple_connection_set_protocol_data + * purple_contact_destroy * purple_global_proxy_set_info + * purple_group_destroy * purple_log_get_activity_score * purple_network_force_online * purple_network_set_stun_server
--- a/libpurple/blist.c Thu Apr 09 01:59:24 2009 +0000 +++ b/libpurple/blist.c Thu Apr 09 17:33:20 2009 +0000 @@ -1202,6 +1202,16 @@ return chat; } +void +purple_chat_destroy(PurpleChat *chat) +{ + g_hash_table_destroy(chat->components); + g_hash_table_destroy(chat->node.settings); + g_free(chat->alias); + PURPLE_DBUS_UNREGISTER_POINTER(chat); + g_free(chat); +} + PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias) { PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); @@ -1229,6 +1239,40 @@ } void +purple_buddy_destroy(PurpleBuddy *buddy) +{ + PurplePlugin *prpl; + PurplePluginProtocolInfo *prpl_info; + + /* + * Tell the owner PRPL that we're about to free the buddy so it + * can free proto_data + */ + prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (prpl_info && prpl_info->buddy_free) + prpl_info->buddy_free(buddy); + + /* Delete the node */ + purple_buddy_icon_unref(buddy->icon); + g_hash_table_destroy(buddy->node.settings); + purple_presence_destroy(buddy->presence); + g_free(buddy->name); + g_free(buddy->alias); + g_free(buddy->server_alias); + + PURPLE_DBUS_UNREGISTER_POINTER(buddy); + g_free(buddy); + + /* FIXME: Once PurpleBuddy is a GObject, timeout callbacks can + * g_object_ref() it when connecting the callback and + * g_object_unref() it in the handler. That way, it won't + * get freed while the timeout is pending and this line can + * be removed. */ + while (g_source_remove_by_user_data((gpointer *)buddy)); +} + +void purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) { g_return_if_fail(buddy != NULL); @@ -1519,6 +1563,14 @@ return contact; } +void +purple_contact_destroy(PurpleContact *contact) +{ + g_hash_table_destroy(contact->node.settings); + PURPLE_DBUS_UNREGISTER_POINTER(contact); + g_free(contact); +} + void purple_contact_set_alias(PurpleContact *contact, const char *alias) { purple_blist_alias_contact(contact,alias); @@ -1588,6 +1640,15 @@ return group; } +void +purple_group_destroy(PurpleGroup *group) +{ + g_hash_table_destroy(group->node.settings); + g_free(group->name); + PURPLE_DBUS_UNREGISTER_POINTER(group); + g_free(group); +} + void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) { PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); @@ -1848,9 +1909,7 @@ ops->remove(purplebuddylist, node); /* Delete the node */ - g_hash_table_destroy(contact->node.settings); - PURPLE_DBUS_UNREGISTER_POINTER(contact); - g_free(contact); + purple_contact_destroy(contact); } } @@ -1861,8 +1920,6 @@ PurpleContact *contact; PurpleGroup *group; struct _purple_hbuddy hb; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; g_return_if_fail(buddy != NULL); @@ -1918,33 +1975,7 @@ /* Signal that the buddy has been removed before freeing the memory for it */ purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); - /* - * Tell the owner PRPL that we're about to free the buddy so it - * can free proto_data - */ - prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); - if (prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && prpl_info->buddy_free) - prpl_info->buddy_free(buddy); - - /* Delete the node */ - purple_buddy_icon_unref(buddy->icon); - g_hash_table_destroy(buddy->node.settings); - purple_presence_destroy(buddy->presence); - g_free(buddy->name); - g_free(buddy->alias); - g_free(buddy->server_alias); - - PURPLE_DBUS_UNREGISTER_POINTER(buddy); - g_free(buddy); - - /* FIXME: Once PurpleBuddy is a GObject, timeout callbacks can - * g_object_ref() it when connecting the callback and - * g_object_unref() it in the handler. That way, it won't - * get freed while the timeout is pending and this line can - * be removed. */ - while (g_source_remove_by_user_data((gpointer *)buddy)); + purple_buddy_destroy(buddy); /* If the contact is empty then remove it */ if ((contact != NULL) && !cnode->child) @@ -1988,11 +2019,7 @@ ops->remove(purplebuddylist, node); /* Delete the node */ - g_hash_table_destroy(chat->components); - g_hash_table_destroy(chat->node.settings); - g_free(chat->alias); - PURPLE_DBUS_UNREGISTER_POINTER(chat); - g_free(chat); + purple_chat_destroy(chat); } void purple_blist_remove_group(PurpleGroup *group) @@ -2033,10 +2060,7 @@ } /* Delete the node */ - g_hash_table_destroy(group->node.settings); - g_free(group->name); - PURPLE_DBUS_UNREGISTER_POINTER(group); - g_free(group); + purple_group_destroy(group); } PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact) @@ -2587,6 +2611,28 @@ } static void +purple_blist_node_destroy(PurpleBlistNode *node) +{ + PurpleBlistNode *child, *next_child; + + child = node->child; + while (child) { + next_child = child->next; + purple_blist_node_destroy(child); + child = next_child; + } + + if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + purple_buddy_destroy((PurpleBuddy*)node); + else if (PURPLE_BLIST_NODE_IS_CHAT(node)) + purple_chat_destroy((PurpleChat*)node); + else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + purple_contact_destroy((PurpleContact*)node); + else if (PURPLE_BLIST_NODE_IS_GROUP(node)) + purple_group_destroy((PurpleGroup*)node); +} + +static void purple_blist_node_setting_free(gpointer data) { PurpleValue *value; @@ -2874,12 +2920,20 @@ void purple_blist_uninit(void) { - if (save_timer != 0) - { + PurpleBlistNode *node, *next_node; + + if (save_timer != 0) { purple_timeout_remove(save_timer); save_timer = 0; purple_blist_sync(); } + node = purple_blist_get_root(); + while (node) { + next_node = node->next; + purple_blist_node_destroy(node); + node = next_node; + } + purple_signals_unregister_by_instance(purple_blist_get_handle()); }
--- a/libpurple/blist.h Thu Apr 09 01:59:24 2009 +0000 +++ b/libpurple/blist.h Thu Apr 09 17:33:20 2009 +0000 @@ -478,6 +478,13 @@ PurpleChat *purple_chat_new(PurpleAccount *account, const char *alias, GHashTable *components); /** + * Destroys a chat + * + * @param chat The chat to destroy + */ +void purple_chat_destroy(PurpleChat *chat); + +/** * Adds a new chat to the buddy list. * * The chat will be inserted right after node or appended to the end @@ -501,6 +508,13 @@ PurpleBuddy *purple_buddy_new(PurpleAccount *account, const char *name, const char *alias); /** + * Destroys a buddy + * + * @param buddy The buddy to destroy + */ +void purple_buddy_destroy(PurpleBuddy *buddy); + +/** * Sets a buddy's icon. * * This should only be called from within Purple. You probably want to @@ -611,6 +625,13 @@ PurpleGroup *purple_group_new(const char *name); /** + * Destroys a group + * + * @param group The group to destroy +*/ +void purple_group_destroy(PurpleGroup *group); + +/** * Adds a new group to the buddy list. * * The new group will be inserted after insert or prepended to the list if @@ -629,6 +650,13 @@ PurpleContact *purple_contact_new(void); /** + * Destroys a contact + * + * @param contact The contact to destroy + */ +void purple_contact_destroy(PurpleContact *contact); + +/** * Adds a new contact to the buddy list. * * The new contact will be inserted after insert or prepended to the list if