/soc/2015/igor.gajowiak/chatlog: 65a053b47b78: Optimized memory ...

Igor Gajowiak igor.gajowiak at gmail.com
Sat Aug 15 13:55:44 EDT 2015


Changeset: 65a053b47b788890565533d2d25522a98d3d163a
Author:	 Igor Gajowiak <igor.gajowiak at gmail.com>
Date:	 2015-08-15 19:55 +0200
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/65a053b47b78

Description:

Optimized memory consumtion. Changed PurpleMessage hashtable so that is keeps weak references.

diffstat:

 finch/gntpounce.c                              |   3 ++
 libpurple/conversation.c                       |  11 ++++++++-
 libpurple/message.c                            |  24 +++++++++++++++++++---
 libpurple/message.h                            |  15 +++++++++----
 libpurple/plugins/log/legacylog.c              |   1 -
 libpurple/plugins/log/logsqlite.c              |   1 -
 libpurple/plugins/offlinemsg.c                 |   7 ++++-
 libpurple/plugins/tcl/tcl_cmds.c               |   7 +++++-
 libpurple/protocols/gg/chat.c                  |   2 +
 libpurple/protocols/gg/message-prpl.c          |   2 +
 libpurple/protocols/irc/cmds.c                 |  27 +++++++++++++++++++------
 libpurple/protocols/jabber/jabber.c            |   7 ++++-
 libpurple/protocols/silc/silc.c                |  26 ++++++++++++++++++------
 libpurple/protocols/yahoo/ymsg.c               |   9 ++++++-
 libpurple/server.c                             |  21 ++++++++++++++++---
 pidgin/gtkpounce.c                             |   2 +
 pidgin/plugins/musicmessaging/musicmessaging.c |  16 +++++++++++---
 17 files changed, 139 insertions(+), 42 deletions(-)

diffs (truncated from 539 to 300 lines):

diff --git a/finch/gntpounce.c b/finch/gntpounce.c
--- a/finch/gntpounce.c
+++ b/finch/gntpounce.c
@@ -876,8 +876,11 @@ pounce_cb(PurplePounce *pounce, PurplePo
 				im = purple_im_conversation_new(account, pouncee);
 
 			pmsg = purple_message_new_outgoing(pouncee, message, 0);
+
 			purple_serv_send_im(purple_account_get_connection(account), pmsg);
 			purple_conversation_write_message(PURPLE_CONVERSATION(im), pmsg);
+
+			g_object_unref(G_OBJECT(pmsg));
 		}
 	}
 
diff --git a/libpurple/conversation.c b/libpurple/conversation.c
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -141,6 +141,8 @@ common_send(PurpleConversation *conv, co
 			purple_signal_emit(purple_conversations_get_handle(),
 				"sent-im-msg", account, msg);
 		}
+
+		g_object_unref(G_OBJECT(msg));
 	}
 	else if (PURPLE_IS_CHAT_CONVERSATION(conv)) {
 		int id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv));
@@ -156,6 +158,8 @@ common_send(PurpleConversation *conv, co
 			purple_signal_emit(purple_conversations_get_handle(),
 				"sent-chat-msg", account, msg, id);
 		}
+
+		g_object_unref(G_OBJECT(msg));
 	}
 
 	if (err < 0) {
@@ -804,8 +808,9 @@ purple_conversation_replace_message(Purp
 void purple_conversation_write_system_message(PurpleConversation *conv,
 	const gchar *message, PurpleMessageFlags flags)
 {
-	_purple_conversation_write_common(conv,
-		purple_message_new_system(message, flags));
+	PurpleMessage *msg = purple_message_new_system(message, flags);
+	_purple_conversation_write_common(conv, msg);
+	g_object_unref(G_OBJECT(msg));
 }
 
 void
@@ -852,6 +857,8 @@ purple_conversation_send_replace_message
 		// Replace message in conversation if sending succeeded
 		if (purple_serv_send_replace_im(gc, replaced_msg_id, msg))
 			purple_conversation_replace_message(conv, replaced_msg_id, msg);
+
+		g_object_unref(G_OBJECT(msg));
 	}
 	else if (PURPLE_IS_CHAT_CONVERSATION(conv)) {
 		// TODO: Do we need to implement this?
diff --git a/libpurple/message.c b/libpurple/message.c
--- a/libpurple/message.c
+++ b/libpurple/message.c
@@ -56,6 +56,11 @@ enum
 static GObjectClass *parent_class;
 static GParamSpec *properties[PROP_LAST];
 
+/*
+ * Contains weak (non-owning) references to #PurpleMessage. Calling
+ * g_object_unref on a message with refcnt equal to 1 automatically removes
+ * entry from this map.
+ */
 static GHashTable *messages = NULL;
 
 /******************************************************************************
@@ -147,7 +152,7 @@ purple_message_find_by_id(guint id)
 {
 	g_return_val_if_fail(id > 0, NULL);
 
-	return g_hash_table_lookup(messages, GINT_TO_POINTER(id));
+	return g_hash_table_lookup(messages, GUINT_TO_POINTER(id));
 }
 
 const gchar *
@@ -259,6 +264,13 @@ generate_next_id()
 	return id++;
 }
 
+static void remove_message_from_hashtable(gpointer data,
+	GObject *where_the_object_was)
+{
+	guint id = GPOINTER_TO_UINT(data);
+	g_hash_table_remove(messages, GUINT_TO_POINTER(id));
+}
+
 static void
 purple_message_init(GTypeInstance *instance, gpointer klass)
 {
@@ -270,7 +282,11 @@ purple_message_init(GTypeInstance *insta
 		purple_marshal_VOID__POINTER, G_TYPE_NONE, 1, PURPLE_TYPE_MESSAGE);
 
 	priv->id = generate_next_id();
-	g_hash_table_insert(messages, GINT_TO_POINTER(priv->id), msg);
+	g_hash_table_insert(messages, GUINT_TO_POINTER(priv->id), msg);
+
+	/* Register a callback for removing weak reference from hash table */
+	g_object_weak_ref(G_OBJECT(msg), remove_message_from_hashtable,
+		GUINT_TO_POINTER(priv->id));
 }
 
 static void
@@ -423,8 +439,8 @@ purple_message_get_type(void)
 void
 _purple_message_init(void)
 {
-	messages = g_hash_table_new_full(g_direct_hash, g_direct_equal,
-		NULL, g_object_unref);
+	/* Hashtable contains non-owning references to PurpleMessage */
+	messages = g_hash_table_new(g_direct_hash, g_direct_equal);
 }
 
 void
diff --git a/libpurple/message.h b/libpurple/message.h
--- a/libpurple/message.h
+++ b/libpurple/message.h
@@ -96,7 +96,8 @@ purple_message_get_type(void);
  *
  * This function should be used when a complete
  * message deserialization is needed. For sending or receiving a message
- * see purple_message_new_outgoing, purple_message_new_incoming.
+ * see purple_message_new_outgoing, purple_message_new_incoming. Message must be
+ * freed using g_object_unref.
  *
  * Returns: the new #PurpleMessage.
  */
@@ -113,7 +114,8 @@ purple_message_new(const gchar *author, 
  *
  * Creates new outgoing message (the user is the author).
  *
- * You don't need to set the #PURPLE_MESSAGE_SEND flag.
+ * You don't need to set the #PURPLE_MESSAGE_SEND flag. Message must be freed
+ * using g_object_unref.
  *
  * Returns: the new #PurpleMessage.
  */
@@ -130,7 +132,8 @@ purple_message_new_outgoing(const gchar 
  *
  * Creates new incoming message (the user is the recipient).
  *
- * You don't need to set the #PURPLE_MESSAGE_RECV flag.
+ * You don't need to set the #PURPLE_MESSAGE_RECV flag. Message must be freed
+ * using g_object_unref.
  *
  * Returns: the new #PurpleMessage.
  */
@@ -145,7 +148,8 @@ purple_message_new_incoming(const gchar 
  *
  * Creates new system message.
  *
- * You don't need to set the #PURPLE_MESSAGE_SYSTEM flag.
+ * You don't need to set the #PURPLE_MESSAGE_SYSTEM flag. Message must be freed
+ * using g_object_unref.
  *
  * Returns: the new #PurpleMessage.
  */
@@ -168,7 +172,8 @@ purple_message_get_id(const PurpleMessag
  * purple_message_find_by_id:
  * @id: The message identifier.
  *
- * Finds the message with a given @id.
+ * Finds the message with a given @id. Does not increase the refcount of
+ * the found message.
  *
  * Returns: the #PurpleMessage, or %NULL if not found.
  */
diff --git a/libpurple/plugins/log/legacylog.c b/libpurple/plugins/log/legacylog.c
--- a/libpurple/plugins/log/legacylog.c
+++ b/libpurple/plugins/log/legacylog.c
@@ -472,7 +472,6 @@ fill_arrays(gchar *text, GArray *account
 
 		g_object_ref(G_OBJECT(acc));
 		g_object_ref(G_OBJECT(contact));
-		g_object_ref(G_OBJECT(msg));
 
 		g_array_append_val(accounts, acc);
 		g_array_append_val(contacts, contact);
diff --git a/libpurple/plugins/log/logsqlite.c b/libpurple/plugins/log/logsqlite.c
--- a/libpurple/plugins/log/logsqlite.c
+++ b/libpurple/plugins/log/logsqlite.c
@@ -755,7 +755,6 @@ sqlitelog_execute_get_msgs_query(sqlite3
 		g_object_set_data(G_OBJECT(msg), SQLITELOG_MESSAGE_ID_ATTR,
 			GUINT_TO_POINTER(id));
 
-		g_object_ref(G_OBJECT(msg));
 		messages = g_list_prepend(messages, msg);
 	}
 
diff --git a/libpurple/plugins/offlinemsg.c b/libpurple/plugins/offlinemsg.c
--- a/libpurple/plugins/offlinemsg.c
+++ b/libpurple/plugins/offlinemsg.c
@@ -108,9 +108,12 @@ record_pounce(OfflineMsg *offline)
 				GINT_TO_POINTER(OFFLINE_MSG_YES));
 
 	/* TODO: use a reference to a PurpleMessage */
-	purple_conversation_write_message(conv,
-		purple_message_new_outgoing(offline->who, offline->message, 0));
+	PurpleMessage *msg = purple_message_new_outgoing(
+		offline->who, offline->message, 0);
 
+	purple_conversation_write_message(conv, msg);
+
+	g_object_unref(G_OBJECT(msg));
 	discard_data(offline);
 }
 
diff --git a/libpurple/plugins/tcl/tcl_cmds.c b/libpurple/plugins/tcl/tcl_cmds.c
--- a/libpurple/plugins/tcl/tcl_cmds.c
+++ b/libpurple/plugins/tcl/tcl_cmds.c
@@ -877,6 +877,7 @@ int tcl_cmd_conversation(ClientData unus
 			break;
 		}
 		purple_conversation_write_message(convo, pmsg);
+		g_object_unref(G_OBJECT(pmsg));
 		break;
 	case CMD_CONV_NAME:
 		if (objc != 3) {
@@ -1413,7 +1414,11 @@ int tcl_cmd_send_im(ClientData unused, T
 	who = Tcl_GetString(objv[2]);
 	text = Tcl_GetString(objv[3]);
 
-	purple_serv_send_im(gc, purple_message_new_outgoing(who, text, 0));
+	PurpleMessage *msg = purple_message_new_outgoing(who, text, 0);
+
+	purple_serv_send_im(gc, msg);
+
+	g_object_unref(G_OBJECT(msg));
 
 	return TCL_OK;
 }
diff --git a/libpurple/protocols/gg/chat.c b/libpurple/protocols/gg/chat.c
--- a/libpurple/protocols/gg/chat.c
+++ b/libpurple/protocols/gg/chat.c
@@ -530,6 +530,8 @@ void ggp_chat_got_message(PurpleConnecti
 
 		purple_conversation_write_message(
 			PURPLE_CONVERSATION(chat->conv), pmsg);
+
+		g_object_unref(G_OBJECT(pmsg));
 	} else {
 		purple_serv_got_chat_in(gc, chat->local_id, ggp_uin_to_str(who),
 			PURPLE_MESSAGE_RECV, message, time);
diff --git a/libpurple/protocols/gg/message-prpl.c b/libpurple/protocols/gg/message-prpl.c
--- a/libpurple/protocols/gg/message-prpl.c
+++ b/libpurple/protocols/gg/message-prpl.c
@@ -241,6 +241,8 @@ static void ggp_message_got_display(Purp
 		purple_message_set_time(pmsg, msg->time);
 
 		purple_conversation_write_message(PURPLE_CONVERSATION(im), pmsg);
+
+		g_object_unref(G_OBJECT(pmsg));
 	} else
 		purple_debug_error("gg", "ggp_message_got_display: "
 			"unexpected message type: %d\n", msg->type);
diff --git a/libpurple/protocols/irc/cmds.c b/libpurple/protocols/irc/cmds.c
--- a/libpurple/protocols/irc/cmds.c
+++ b/libpurple/protocols/irc/cmds.c
@@ -122,8 +122,11 @@ int irc_cmd_ctcp_action(struct irc_conn 
 	}
 
 	g_free(msg);
-	if (purple_message_is_empty(pmsg))
+	if (purple_message_is_empty(pmsg)) {
+		g_object_unref(G_OBJECT(pmsg));
 		return 0;
+	}
+
 	msg = g_strdup(purple_message_get_contents(pmsg)); /* XXX: is it really necessary? */
 
 	if (strncmp(msg, "/me ", 4) != 0) {
@@ -188,12 +191,18 @@ int irc_cmd_ctcp_action(struct irc_conn 
 			purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(convo)),
 			                 purple_connection_get_display_name(gc),
 			                 PURPLE_MESSAGE_SEND, action, time(NULL));
-		else
-			purple_conversation_write_message(convo, purple_message_new_outgoing(
-				purple_connection_get_display_name(gc), action, 0));
+		else {
+			PurpleMessage *pmsg2 = purple_message_new_outgoing(
+				purple_connection_get_display_name(gc), action, 0);
+
+			purple_conversation_write_message(convo, pmsg2);
+
+			g_object_unref(G_OBJECT(pmsg2));
+		}
 		g_free(action);
 	}
 
+	g_object_unref(G_OBJECT(pmsg));
 	return 1;
 }
 
@@ -501,9 +510,13 @@ int irc_cmd_query(struct irc_conn *irc, 
 	if (args[1]) {



More information about the Commits mailing list