[Galago-commits] r2641 - in trunk/libgalago: . libgalago

galago-commits at freedesktop.org galago-commits at freedesktop.org
Thu Mar 30 15:37:59 PST 2006


Author: chipx86
Date: 2006-03-30 15:37:50 -0800 (Thu, 30 Mar 2006)
New Revision: 2641

Modified:
   trunk/libgalago/ChangeLog
   trunk/libgalago/NEWS
   trunk/libgalago/libgalago/galago-account.c
   trunk/libgalago/libgalago/galago-context.c
   trunk/libgalago/libgalago/galago-core.c
   trunk/libgalago/libgalago/galago-person.c
   trunk/libgalago/libgalago/galago-service.c
   trunk/libgalago/libgalago/galago-service.h
   trunk/libgalago/libgalago/galago-status.c
Log:
- Added better threading support. All global/static variables are now locked.
- Fixed a memory leak in GalagoPerson where session IDs weren't being freed.
- Changed galago_service_normalize() to return an allocated string instead of a static buffer. Also rewrote this to use GString and to hopefully be a little more efficient.
- Used GOnce where appropriate to initialize certain things only once.


Modified: trunk/libgalago/ChangeLog
===================================================================
--- trunk/libgalago/ChangeLog	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/ChangeLog	2006-03-30 23:37:50 UTC (rev 2641)
@@ -1,3 +1,22 @@
+Thu Mar 30 15:34:06 PST 2006  Christian Hammond <chipx86 at chipx86.com>
+
+	* libgalago/galago-account.c:
+	* libgalago/galago-context.c:
+	* libgalago/galago-core.c:
+	* libgalago/galago-person.c:
+	* libgalago/galago-service.c:
+	* libgalago/galago-service.h:
+	* libgalago/galago-status.c:
+	* NEWS:
+	  - Added better threading support. All global/static variables are
+	    now locked.
+	  - Fixed a memory leak in GalagoPerson where session IDs weren't being
+	    freed.
+	  - Changed galago_service_normalize() to return an allocated string
+	    instead of a static buffer. Also rewrote this to use GString and to
+	    hopefully be a little more efficient.
+	  - Used GOnce where appropriate to initialize certain things only once.
+
 Wed Mar 29 22:15:25 PST 2006  Christian Hammond <chipx86 at chipx86.com>
 
 	* libgalago/galago-dbus.c:

Modified: trunk/libgalago/NEWS
===================================================================
--- trunk/libgalago/NEWS	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/NEWS	2006-03-30 23:37:50 UTC (rev 2641)
@@ -6,6 +6,7 @@
 	* "Added" signals are no longer blocked when retrieving a list of new
 	  objects. Updated the docs to warn about potential problems in the users'
 	  code that they should know about.
+	* Worked toward making libgalago more thread-safe.
 
 	GLib port:
 		- Replaced the home-brewn object model with GObject.
@@ -97,6 +98,9 @@
 		- galago_service_new() has been removed.
 		  galago_create_service() should now be used.
 		- Clients can no longer create a foreign service.
+		- galago_service_normalize() now returns a pre-allocated string.
+		  If you use this, make sure you're freeing the returned string
+		  when no longer in use.
 
 	GalagoStatus:
 		- Added a GALAGO_STATUS_ATTR_MESSAGE define.

Modified: trunk/libgalago/libgalago/galago-account.c
===================================================================
--- trunk/libgalago/libgalago/galago-account.c	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/libgalago/galago-account.c	2006-03-30 23:37:50 UTC (rev 2641)
@@ -735,8 +735,8 @@
 	service = galago_account_get_service(account);
 
 	g_hash_table_insert(account->priv->contacts_table,
-		g_strdup(galago_service_normalize(service, username)),
-		contact);
+						galago_service_normalize(service, username),
+						contact);
 
 	account->priv->contacts = g_list_append(account->priv->contacts, contact);
 
@@ -778,6 +778,7 @@
 {
 	GalagoAccount *contact;
 	GalagoService *service;
+	char *norm_username;
 
 	g_return_val_if_fail(account != NULL,                       NULL);
 	g_return_val_if_fail(GALAGO_IS_ACCOUNT(account),            NULL);
@@ -785,9 +786,10 @@
 
 	service = galago_account_get_service(account);
 
-	contact =
-		g_hash_table_lookup(account->priv->contacts_table,
-							galago_service_normalize(service, username));
+	norm_username = galago_service_normalize(service, username);
+	contact = g_hash_table_lookup(account->priv->contacts_table,
+								  norm_username);
+	g_free(norm_username);
 
 	if (contact == NULL && query && GALAGO_OBJECT_IS_REMOTE(account) &&
 		!galago_is_daemon() && galago_is_connected())

Modified: trunk/libgalago/libgalago/galago-context.c
===================================================================
--- trunk/libgalago/libgalago/galago-context.c	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/libgalago/galago-context.c	2006-03-30 23:37:50 UTC (rev 2641)
@@ -71,9 +71,11 @@
  **************************************************************************/
 static void galago_context_destroy(GalagoObject *gobject);
 
-static GalagoObjectClass *parent_class = NULL;
+G_LOCK_DEFINE_STATIC(_contexts_lock);
 static GList *contexts = NULL;
 
+static GalagoObjectClass *parent_class = NULL;
+
 G_DEFINE_TYPE(GalagoContext, galago_context, GALAGO_TYPE_OBJECT);
 
 static void
@@ -217,16 +219,24 @@
 	g_return_if_fail(context != NULL);
 	g_return_if_fail(GALAGO_IS_CONTEXT(context));
 
+	G_LOCK(_contexts_lock);
 	contexts = g_list_prepend(contexts, context);
+	G_UNLOCK(_contexts_lock);
 }
 
 void
 galago_context_pop(void)
 {
-	GalagoContext *context = galago_context_get();
+	GalagoContext *context;
 
+	G_LOCK(_contexts_lock);
+
+	context = galago_context_get();
+
 	if (context != NULL)
 		contexts = g_list_remove(contexts, context);
+
+	G_UNLOCK(_contexts_lock);
 }
 
 GalagoContext *

Modified: trunk/libgalago/libgalago/galago-core.c
===================================================================
--- trunk/libgalago/libgalago/galago-core.c	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/libgalago/galago-core.c	2006-03-30 23:37:50 UTC (rev 2641)
@@ -102,8 +102,8 @@
 static void _galago_dbus_core_add_person(GalagoPerson *person);
 static void _galago_dbus_core_remove_person(GalagoPerson *person);
 
+G_LOCK_DEFINE_STATIC(_core_lock);
 static GalagoCore *_core = NULL;
-static gboolean first_init = TRUE;
 
 static GalagoContextOps context_ops =
 {
@@ -234,9 +234,12 @@
 static void
 galago_core_init(GalagoCore *core)
 {
+	G_LOCK(_core_lock);
+
 	_core = core;
+	galago_object_set_dbus_path(GALAGO_OBJECT(core), GALAGO_DBUS_CORE_OBJECT);
 
-	galago_object_set_dbus_path(GALAGO_OBJECT(core), GALAGO_DBUS_CORE_OBJECT);
+	G_UNLOCK(_core_lock);
 }
 
 static void
@@ -265,7 +268,9 @@
 	if (_core->conn_obj_path != NULL)
 		g_free(_core->conn_obj_path);
 
+	G_LOCK(_core_lock);
 	_core = NULL;
+	G_UNLOCK(_core_lock);
 
 	G_OBJECT_CLASS(parent_class)->finalize(object);
 }
@@ -828,10 +833,26 @@
 }
 #endif
 
+static gpointer
+register_exit_handlers(gpointer unused)
+{
+	g_atexit(_exit_galago);
+
+#ifdef HAVE_SIGNAL_H
+	if (signal(SIGINT, _sigint_cb) == SIG_ERR)
+	{
+		g_warning("Unable to register SIGINT signal handler");
+	}
+#endif /* HAVE_SIGNAL_H_ */
+
+	return NULL;
+}
+
 gboolean
 galago_init(const char *name, gboolean feed)
 {
 	GalagoContext *context;
+	static GOnce first_init = G_ONCE_INIT;
 
 	g_return_val_if_fail(name  != NULL, FALSE);
 	g_return_val_if_fail(*name != '\0', FALSE);
@@ -850,7 +871,9 @@
 
 	galago_context_push(context);
 
+	G_LOCK(_core_lock);
 	_core = g_object_new(GALAGO_TYPE_CORE, NULL);
+	G_UNLOCK(_core_lock);
 
 	_core->app_name = g_strdup(name);
 	_core->feed = feed;
@@ -861,20 +884,8 @@
 	if (!_galago_core_connect())
 		_galago_core_disconnect();
 
-	if (first_init)
-	{
-		g_atexit(_exit_galago);
+	g_once(&first_init, register_exit_handlers, NULL);
 
-#ifdef HAVE_SIGNAL_H
-		if (signal(SIGINT, _sigint_cb) == SIG_ERR)
-		{
-			g_warning("Unable to register SIGINT signal handler");
-		}
-#endif /* HAVE_SIGNAL_H_ */
-
-		first_init = TRUE;
-	}
-
 	return TRUE;
 }
 

Modified: trunk/libgalago/libgalago/galago-person.c
===================================================================
--- trunk/libgalago/libgalago/galago-person.c	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/libgalago/galago-person.c	2006-03-30 23:37:50 UTC (rev 2641)
@@ -32,6 +32,7 @@
 {
 	char *id;
 	char *session_id;
+	char *display_name;
 	GalagoImage *photo;
 	GHashTable *accounts_table;
 	GList *accounts;
@@ -219,9 +220,9 @@
 		galago_context_remove_person(person);
 		galago_context_pop();
 
-		if (person->priv->id != NULL)
-			g_free(person->priv->id);
-
+		g_free(person->priv->id);
+		g_free(person->priv->session_id);
+		g_free(person->priv->display_name);
 		g_free(person->priv);
 		person->priv = NULL;
 	}
@@ -392,13 +393,16 @@
 GalagoPerson *
 galago_create_person(const char *uid)
 {
+	G_LOCK_DEFINE_STATIC(session_id_lock);
 	static gulong next_session_id_index = 1;
 	char *session_id = NULL;
 	GalagoPerson *person;
 
 	g_return_val_if_fail(galago_is_initted(), NULL);
 
+	G_LOCK(session_id_lock);
 	session_id = g_strdup_printf("session-id-%ld", next_session_id_index++);
+	G_UNLOCK(session_id_lock);
 
 	person = _galago_person_new(uid, session_id, GALAGO_LOCAL, NULL);
 
@@ -480,7 +484,6 @@
 const char *
 galago_person_get_display_name(const GalagoPerson *person)
 {
-	static char buffer[BUFSIZ];
 	const char *first_name, *last_name;
 
 	g_return_val_if_fail(person != NULL,           NULL);
@@ -488,6 +491,9 @@
 
 	/* XXX This is all a hack, but for now, it should work. Improve this! */
 
+	g_free(person->priv->display_name);
+	person->priv->display_name = NULL;
+
 	first_name = galago_object_get_attr_string(GALAGO_OBJECT(person),
 											   GALAGO_PERSON_ATTR_FIRST_NAME);
 	last_name = galago_object_get_attr_string(GALAGO_OBJECT(person),
@@ -495,15 +501,13 @@
 
 	if (first_name != NULL || last_name != NULL)
 	{
-		g_snprintf(buffer, sizeof(buffer), "%s%s%s",
-				   (first_name == NULL ? "" : first_name),
-				   (first_name != NULL && last_name != NULL ? " " : ""),
-				   (last_name == NULL ? "" : last_name));
-
-		return buffer;
+		person->priv->display_name = g_strdup_printf("%s%s%s",
+			(first_name == NULL ? "" : first_name),
+			(first_name != NULL && last_name != NULL ? " " : ""),
+			(last_name == NULL ? "" : last_name));
 	}
 
-	return NULL;
+	return person->priv->display_name;
 }
 
 void
@@ -671,7 +675,7 @@
 	}
 
 	key = g_new0(AccountCacheKey, 1);
-	key->username = g_strdup(galago_service_normalize(service, username));
+	key->username = galago_service_normalize(service, username);
 	key->service  = service;
 
 	g_hash_table_insert(person->priv->accounts_table, key, account);
@@ -696,7 +700,7 @@
 	service  = galago_account_get_service(account);
 	username = galago_account_get_username(account);
 
-	key.username = g_strdup(galago_service_normalize(service, username));
+	key.username = galago_service_normalize(service, username);
 	key.service  = galago_account_get_service(account);
 
 	g_hash_table_remove(person->priv->accounts_table, &key);
@@ -726,7 +730,7 @@
 						 galago_object_get_origin(GALAGO_OBJECT(service)),
 						 NULL);
 
-	key.username = g_strdup(galago_service_normalize(service, username));
+	key.username = galago_service_normalize(service, username);
 	key.service  = service;
 
 	account = g_hash_table_lookup(person->priv->accounts_table, &key);

Modified: trunk/libgalago/libgalago/galago-service.c
===================================================================
--- trunk/libgalago/libgalago/galago-service.c	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/libgalago/galago-service.c	2006-03-30 23:37:50 UTC (rev 2641)
@@ -340,8 +340,8 @@
 	g_free(map_info);
 }
 
-static void
-_init_service_id_map_table(void)
+static gpointer
+_init_service_id_map_table(gpointer unused)
 {
 	ServiceMapInfo *map_info;
 
@@ -368,19 +368,21 @@
 					GALAGO_PRESERVE_SPACES);
 	ADD_SERVICE_MAP(GALAGO_SERVICE_ID_ZEPHYR,    _("Zephyr"),
 					GALAGO_PRESERVE_SPACES | GALAGO_PRESERVE_CASE);
+
+	return NULL;
 }
 
 static ServiceMapInfo *
 _galago_services_map_id_to_info(const char *id)
 {
+	static GOnce map_init = G_ONCE_INIT;
 	ServiceMapInfo *map_info;
 	char *temp;
 
 	g_return_val_if_fail(id  != NULL, NULL);
 	g_return_val_if_fail(*id != '\0', NULL);
 
-	if (service_id_map_table == NULL)
-		_init_service_id_map_table();
+	g_once(&map_init, _init_service_id_map_table, NULL);
 
 	temp = g_ascii_strdown(id, -1);
 
@@ -489,14 +491,16 @@
 						   gboolean query)
 {
 	GalagoAccount *account;
+	char *norm_username;
 
 	g_return_val_if_fail(service  != NULL,           NULL);
 	g_return_val_if_fail(username != NULL,           NULL);
 	g_return_val_if_fail(GALAGO_IS_SERVICE(service), NULL);
 
-	account = g_hash_table_lookup(
-		service->priv->accounts_table,
-		galago_service_normalize(service, username));
+	norm_username = galago_service_normalize(service, username);
+	account = g_hash_table_lookup(service->priv->accounts_table,
+								  norm_username);
+	g_free(norm_username);
 
 	if (account == NULL && query && GALAGO_OBJECT_IS_REMOTE(service) &&
 		!galago_is_daemon() && galago_is_connected())
@@ -563,8 +567,7 @@
 	}
 
 	g_hash_table_insert(service->priv->accounts_table,
-		g_strdup(galago_service_normalize(service, username)),
-		account);
+						galago_service_normalize(service, username), account);
 
 	service->priv->accounts = g_list_append(service->priv->accounts, account);
 
@@ -578,6 +581,7 @@
 _galago_service_remove_account(GalagoService *service, GalagoAccount *account)
 {
 	const char *username;
+	char *norm_username;
 
 	g_return_if_fail(service != NULL);
 	g_return_if_fail(account != NULL);
@@ -585,10 +589,10 @@
 	g_return_if_fail(GALAGO_IS_ACCOUNT(account));
 
 	username = galago_account_get_username(account);
+	norm_username = galago_service_normalize(service, username);
+	g_hash_table_remove(service->priv->accounts_table, norm_username);
+	g_free(norm_username);
 
-	g_hash_table_remove(service->priv->accounts_table,
-						galago_service_normalize(service, username));
-
 	service->priv->accounts = g_list_remove(service->priv->accounts, account);
 
 	if (GALAGO_OBJECT_IS_LOCAL(service) && galago_is_connected() &&
@@ -602,12 +606,12 @@
 	g_signal_emit(service, signals[ACCOUNT_REMOVED], 0, account);
 }
 
-const char *
+char *
 galago_service_normalize(const GalagoService *service, const char *username)
 {
-	static char buffer[BUFSIZ];
+	GString *str;
+	char *buffer;
 	const char *c;
-	char *d;
 	GalagoServiceFlags flags;
 
 	g_return_val_if_fail(service  != NULL,           NULL);
@@ -616,7 +620,11 @@
 
 	flags = galago_service_get_flags(service);
 
-	for (c = username, d = buffer; *c != '\0'; c++)
+	str = g_string_new("");
+
+	for (c = username;
+		 *c != '\0' && (!(flags & GALAGO_STRIP_SLASH) || *c != '/');
+		 c++)
 	{
 		if (*c == ' ' && (flags & GALAGO_PRESERVE_SPACES) == 0)
 		{
@@ -624,23 +632,13 @@
 				c++;
 		}
 
-		*d++ = *c;
+		g_string_append_c(str, *c);
 	}
 
-	*d = '\0';
-
 	if ((flags & GALAGO_PRESERVE_CASE) == 0)
-	{
-		char *tmp = g_ascii_strdown(buffer, -1);
-		strncpy(buffer, tmp, sizeof(buffer));
-		g_free(tmp);
-	}
+		g_string_ascii_down(str);
 
-	if ((flags & GALAGO_STRIP_SLASH) == GALAGO_STRIP_SLASH &&
-		(d = strchr(buffer, '/')) != NULL)
-	{
-		*d = '\0';
-	}
+	buffer = g_string_free(str, FALSE);
 
 	return buffer;
 }

Modified: trunk/libgalago/libgalago/galago-service.h
===================================================================
--- trunk/libgalago/libgalago/galago-service.h	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/libgalago/galago-service.h	2006-03-30 23:37:50 UTC (rev 2641)
@@ -222,16 +222,13 @@
  * Normalizes an account username based on the service's normalization
  * flags.
  *
- * The returned string is stored internally in a status buffer. If you need
- * the string for long, make sure to g_strdup() it.
- *
  * @param service  The service.
  * @param username The username to normalize.
  *
- * @return The string, stored in a static buffer.
+ * @return The string. This must be freed.
  */
-const char *galago_service_normalize(const GalagoService *service,
-									 const char *username);
+char *galago_service_normalize(const GalagoService *service,
+							   const char *username);
 
 /*@}*/
 

Modified: trunk/libgalago/libgalago/galago-status.c
===================================================================
--- trunk/libgalago/libgalago/galago-status.c	2006-03-30 06:16:00 UTC (rev 2640)
+++ trunk/libgalago/libgalago/galago-status.c	2006-03-30 23:37:50 UTC (rev 2641)
@@ -442,8 +442,8 @@
 #define ADD_STATUS_MAP(id, name) \
 	g_hash_table_insert(status_id_map_table, g_strdup(id), g_strdup(name));
 
-static void
-_init_status_id_map_table(void)
+static gpointer
+_init_status_id_map_table(gpointer unused)
 {
 	status_id_map_table =
 		g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
@@ -456,16 +456,19 @@
 	ADD_STATUS_MAP(GALAGO_STATUS_ID_EXTENDED_AWAY, _("Extended Away"));
 	ADD_STATUS_MAP(GALAGO_STATUS_ID_HIDDEN,        _("Hidden"));
 	ADD_STATUS_MAP(GALAGO_STATUS_ID_OFFLINE,       _("Offline"));
+
+	return NULL;
 }
 
 static const char *
 _galago_statuses_map_id_to_name(const char *id)
 {
+	static GOnce map_init = G_ONCE_INIT;
+
 	g_return_val_if_fail(id  != NULL, NULL);
 	g_return_val_if_fail(*id != '\0', NULL);
 
-	if (status_id_map_table == NULL)
-		_init_status_id_map_table();
+	g_once(&map_init, _init_status_id_map_table, NULL);
 
 	return (const char *)g_hash_table_lookup(status_id_map_table, id);
 }



More information about the galago-commits mailing list