? depcomp
? py-compile
? po/stamp-it
Index: libmenu/desktop-entries.c
===================================================================
RCS file: /cvs/gnome/gnome-menus/libmenu/desktop-entries.c,v
retrieving revision 1.13
diff -p -u -r1.13 desktop-entries.c
--- libmenu/desktop-entries.c	5 May 2006 15:27:06 -0000	1.13
+++ libmenu/desktop-entries.c	2 Aug 2006 18:45:41 -0000
@@ -51,12 +51,12 @@ struct DesktopEntry
 
   guint type : 2;
   guint flags : 4;
-  guint refcount : 24;
+  volatile gint refcount;
 };
 
 struct DesktopEntrySet
 {
-  int         refcount;
+  volatile int refcount;
   GHashTable *hash;
 };
 
@@ -372,7 +372,7 @@ desktop_entry_ref (DesktopEntry *entry)
   g_return_val_if_fail (entry != NULL, NULL);
   g_return_val_if_fail (entry->refcount > 0, NULL);
 
-  entry->refcount += 1;
+  g_atomic_int_inc (&entry->refcount);
 
   return entry;
 }
@@ -420,11 +420,13 @@ desktop_entry_copy (DesktopEntry *entry)
 void
 desktop_entry_unref (DesktopEntry *entry)
 {
+  gboolean is_zero;
+
   g_return_if_fail (entry != NULL);
   g_return_if_fail (entry->refcount > 0);
 
-  entry->refcount -= 1;
-  if (entry->refcount == 0)
+  is_zero = g_atomic_int_dec_and_test (&entry->refcount);
+  if (is_zero)
     {
       g_free (entry->categories);
       entry->categories = NULL;
@@ -604,7 +606,7 @@ desktop_entry_set_ref (DesktopEntrySet *
   g_return_val_if_fail (set != NULL, NULL);
   g_return_val_if_fail (set->refcount > 0, NULL);
 
-  set->refcount += 1;
+  g_atomic_int_inc (&set->refcount);
 
   return set;
 }
@@ -612,11 +614,13 @@ desktop_entry_set_ref (DesktopEntrySet *
 void
 desktop_entry_set_unref (DesktopEntrySet *set)
 {
+  gboolean is_zero;
+
   g_return_if_fail (set != NULL);
   g_return_if_fail (set->refcount > 0);
 
-  set->refcount -= 1;
-  if (set->refcount == 0)
+  is_zero = g_atomic_int_dec_and_test (&set->refcount);
+  if (is_zero)
     {
       menu_verbose (" Deleting entry set %p\n", set);
 
Index: libmenu/entry-directories.c
===================================================================
RCS file: /cvs/gnome/gnome-menus/libmenu/entry-directories.c,v
retrieving revision 1.17
diff -p -u -r1.17 entry-directories.c
--- libmenu/entry-directories.c	22 Aug 2005 08:19:34 -0000	1.17
+++ libmenu/entry-directories.c	2 Aug 2006 18:45:41 -0000
@@ -40,12 +40,12 @@ struct EntryDirectory
 
   guint entry_type : 2;
   guint is_legacy : 1;
-  guint refcount : 24;
+  volatile gint refcount;
 };
 
 struct EntryDirectoryList
 {
-  int    refcount;
+  volatile int refcount;
   int    length;
   GList *dirs;
 };
@@ -64,7 +64,10 @@ struct CachedDir
   guint have_read_entries : 1;
   guint deleted : 1;
 
-  guint references : 28;
+  GFunc    notify;
+  gpointer notify_data;
+
+  volatile gint references;
 };
 
 struct CachedDirMonitor
@@ -74,9 +77,14 @@ struct CachedDirMonitor
   gpointer                   user_data;
 };
 
-static void     cached_dir_free                   (CachedDir  *dir);
-static gboolean cached_dir_load_entries_recursive (CachedDir  *dir,
-                                                   const char *dirname);
+static void       cached_dir_unref                  (CachedDir  *dir);
+static CachedDir *cached_dir_add_subdir             (CachedDir  *dir,
+                                                     const char *basename,
+                                                     const char *path);
+static gboolean   cached_dir_remove_subdir          (CachedDir  *dir,
+                                                     const char *basename);
+static gboolean   cached_dir_load_entries_recursive (CachedDir  *dir,
+                                                     const char *dirname);
 
 static void handle_cached_dir_changed (MenuMonitor      *monitor,
 				       MenuMonitorEvent  event,
@@ -101,6 +109,21 @@ cached_dir_new (const char *name)
   return dir;
 }
 
+static CachedDir *
+cached_dir_new_full (const char *name,
+                     GFunc       notify,
+                     gpointer    notify_data)
+{
+  CachedDir *dir;
+
+  dir = cached_dir_new (name);
+
+  dir->notify = notify;
+  dir->notify_data = notify_data;
+
+  return dir;
+}
+
 static void
 cached_dir_free (CachedDir *dir)
 {
@@ -124,7 +147,7 @@ cached_dir_free (CachedDir *dir)
   dir->entries = NULL;
 
   g_slist_foreach (dir->subdirs,
-                   (GFunc) cached_dir_free,
+                   (GFunc) cached_dir_unref,
                    NULL);
   g_slist_free (dir->subdirs);
   dir->subdirs = NULL;
@@ -133,6 +156,38 @@ cached_dir_free (CachedDir *dir)
   g_free (dir);
 }
 
+static CachedDir *
+cached_dir_ref (CachedDir *dir)
+{
+  g_atomic_int_inc (&dir->references);
+
+  return dir;
+}
+
+static void
+cached_dir_unref (CachedDir *dir)
+{
+  gboolean is_zero;
+
+  is_zero = g_atomic_int_dec_and_test (&dir->references);
+  if (is_zero)
+    {
+      CachedDir *parent;
+
+      parent = dir->parent;
+
+      if (parent != NULL)
+	{
+          cached_dir_remove_subdir (parent, dir->name);
+	}
+
+      if (dir->notify)
+        dir->notify (dir, dir->notify_data);
+
+      cached_dir_free (dir);
+    }
+}
+
 static inline CachedDir *
 find_subdir (CachedDir  *dir,
              const char *subdir)
@@ -162,8 +217,13 @@ find_entry (CachedDir  *dir,
   tmp = dir->entries;
   while (tmp != NULL)
     {
-      if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
-        return tmp->data;
+      const char *entry_basename;
+
+      entry_basename = desktop_entry_get_basename (tmp->data);
+      if (strcmp (entry_basename, basename) == 0)
+        {
+          return tmp->data;
+        }
 
       tmp = tmp->next;
     }
@@ -179,7 +239,7 @@ cached_dir_find_relative_path (CachedDir
   char         **split;
   int            i;
 
-  split = g_strsplit (relative_path, "/", -1);
+  split = g_strsplit (relative_path, G_DIR_SEPARATOR_S, -1);
 
   i = 0;
   while (split[i] != NULL)
@@ -203,6 +263,14 @@ cached_dir_find_relative_path (CachedDir
   return retval;
 }
 
+static void
+clear_cache (CachedDir *dir,
+             gpointer  *cache)
+{
+  menu_verbose ("Clearing cached toplevel dir\n");
+  g_nullify_pointer (cache);
+}
+
 static CachedDir *
 cached_dir_lookup (const char *canonical)
 {
@@ -211,26 +279,25 @@ cached_dir_lookup (const char *canonical
   int         i;
 
   if (dir_cache == NULL)
-    dir_cache = cached_dir_new ("/");
+    {
+      dir_cache = cached_dir_new_full (G_DIR_SEPARATOR_S, (GFunc)clear_cache, &dir_cache);
+    }
   dir = dir_cache;
 
-  g_assert (canonical != NULL && canonical[0] == '/');
+  g_assert (canonical != NULL && canonical[0] == G_DIR_SEPARATOR);
 
   menu_verbose ("Looking up cached dir \"%s\"\n", canonical);
 
-  split = g_strsplit (canonical + 1, "/", -1);
+  split = g_strsplit (canonical + 1, G_DIR_SEPARATOR_S, -1);
 
   i = 0;
   while (split[i] != NULL)
     {
       CachedDir *subdir;
 
-      if ((subdir = find_subdir (dir, split[i])) == NULL)
-        {
-          subdir = cached_dir_new (split[i]);
-          dir->subdirs = g_slist_prepend (dir->subdirs, subdir);
-          subdir->parent = dir;
-        }
+      menu_verbose ("Adding sub dir \"%s\"\n", split[i]);
+
+      subdir = cached_dir_add_subdir (dir, split[i], NULL);
 
       dir = subdir;
 
@@ -270,7 +337,9 @@ cached_dir_update_entry (CachedDir  *dir
   tmp = dir->entries;
   while (tmp != NULL)
     {
-      if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
+      const char *entry_basename;
+      entry_basename = desktop_entry_get_basename (tmp->data);
+      if (strcmp (entry_basename, basename) == 0)
         {
           if (!desktop_entry_reload (tmp->data))
 	    {
@@ -295,7 +364,10 @@ cached_dir_remove_entry (CachedDir  *dir
   tmp = dir->entries;
   while (tmp != NULL)
     {
-      if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
+      const char *entry_basename;
+      entry_basename = desktop_entry_get_basename (tmp->data);
+
+      if (strcmp (entry_basename, basename) == 0)
         {
           desktop_entry_unref (tmp->data);
           dir->entries = g_slist_delete_link (dir->entries, tmp);
@@ -308,69 +380,55 @@ cached_dir_remove_entry (CachedDir  *dir
   return FALSE;
 }
 
-static gboolean
+static CachedDir *
 cached_dir_add_subdir (CachedDir  *dir,
                        const char *basename,
                        const char *path)
 {
   CachedDir *subdir;
-  GSList    *tmp;
 
-  tmp = dir->subdirs;
-  while (tmp != NULL)
+  subdir = find_subdir (dir, basename);
+  if (subdir != NULL)
     {
-      subdir = (CachedDir *) tmp->data;
-
-      if (strcmp (subdir->name, basename) == 0)
-        {
-	  subdir->deleted = FALSE;
-          return TRUE;
-        }
-
-      tmp = tmp->next;
+      subdir->deleted = FALSE;
+      return subdir;
     }
 
   subdir = cached_dir_new (basename);
 
-  if (!cached_dir_load_entries_recursive (subdir, path))
+  if (path != NULL && !cached_dir_load_entries_recursive (subdir, path))
     {
       cached_dir_free (subdir);
-      return FALSE;
+      return NULL;
     }
 
   menu_verbose ("Caching dir \"%s\"\n", basename);
 
   subdir->parent = dir;
-  dir->subdirs = g_slist_prepend (dir->subdirs, subdir);
 
-  return TRUE;
+  dir->subdirs = g_slist_prepend (dir->subdirs, cached_dir_ref (subdir));
+
+  return subdir;
 }
 
 static gboolean
 cached_dir_remove_subdir (CachedDir  *dir,
                           const char *basename)
 {
-  GSList *tmp;
+  CachedDir *subdir;
 
-  tmp = dir->subdirs;
-  while (tmp != NULL)
+  subdir = find_subdir (dir, basename);
+  if (subdir != NULL)
     {
-      CachedDir *subdir = tmp->data;
+      subdir->deleted = TRUE;
 
-      if (strcmp (subdir->name, basename) == 0)
+      if (g_atomic_int_get (&subdir->references) == 0)
         {
-	  subdir->deleted = TRUE;
-
-	  if (subdir->references == 0)
-	    {
-	      cached_dir_free (subdir);
-	      dir->subdirs = g_slist_delete_link (dir->subdirs, tmp);
-	    }
-
-          return TRUE;
+          dir->subdirs = g_slist_remove (dir->subdirs, subdir);
+          cached_dir_unref (subdir);
         }
 
-      tmp = tmp->next;
+      return TRUE;
     }
 
   return FALSE;
@@ -443,7 +501,7 @@ handle_cached_dir_changed (MenuMonitor  
       switch (event)
         {
         case MENU_MONITOR_EVENT_CREATED:
-          handled = cached_dir_add_subdir (dir, basename, path);
+          handled = cached_dir_add_subdir (dir, basename, path) != NULL;
           break;
 
         case MENU_MONITOR_EVENT_CHANGED:
@@ -509,8 +567,8 @@ cached_dir_load_entries_recursive (Cache
   cached_dir_ensure_monitor (dir, dirname);
 
   fullpath = g_string_new (dirname);
-  if (fullpath->str[fullpath->len - 1] != '/')
-    g_string_append_c (fullpath, '/');
+  if (fullpath->str[fullpath->len - 1] != G_DIR_SEPARATOR)
+    g_string_append_c (fullpath, G_DIR_SEPARATOR);
 
   fullpath_len = fullpath->len;
 
@@ -609,7 +667,7 @@ cached_dir_remove_monitor (CachedDir    
 static void
 cached_dir_add_reference (CachedDir *dir)
 {
-  dir->references++;
+  cached_dir_ref (dir);
 
   if (dir->parent != NULL)
     {
@@ -624,29 +682,7 @@ cached_dir_remove_reference (CachedDir *
 
   parent = dir->parent;
 
-  if (--dir->references == 0 && dir->deleted)
-    {
-      if (dir->parent != NULL)
-	{
-	  GSList *tmp;
-
-	  tmp = parent->subdirs;
-	  while (tmp != NULL)
-	    {
-	      CachedDir *subdir = tmp->data;
-
-	      if (!strcmp (subdir->name, dir->name))
-		{
-		  parent->subdirs = g_slist_delete_link (parent->subdirs, tmp);
-		  break;
-		}
-
-	      tmp = tmp->next;
-	    }
-	}
-
-      cached_dir_free (dir);
-    }
+  cached_dir_unref (dir);
 
   if (parent != NULL)
     {
@@ -718,7 +754,7 @@ entry_directory_ref (EntryDirectory *ed)
   g_return_val_if_fail (ed != NULL, NULL);
   g_return_val_if_fail (ed->refcount > 0, NULL);
 
-  ed->refcount++;
+  g_atomic_int_inc (&ed->refcount);
 
   return ed;
 }
@@ -726,10 +762,13 @@ entry_directory_ref (EntryDirectory *ed)
 void
 entry_directory_unref (EntryDirectory *ed)
 {
+  gboolean is_zero;
+
   g_return_if_fail (ed != NULL);
   g_return_if_fail (ed->refcount > 0);
 
-  if (--ed->refcount == 0)
+  is_zero = g_atomic_int_dec_and_test (&ed->refcount);
+  if (is_zero)
     {
       cached_dir_remove_reference (ed->dir);
 
@@ -789,7 +828,7 @@ get_desktop_file_id_from_path (EntryDire
     {
       if (!ed->is_legacy)
 	{
-	  retval = g_strdelimit (g_strdup (relative_path), "/", '-');
+	  retval = g_strdelimit (g_strdup (relative_path), G_DIR_SEPARATOR_S, '-');
 	}
       else
 	{
@@ -845,11 +884,12 @@ entry_directory_foreach_recursive (Entry
 
       if (desktop_entry_get_type (entry) == ed->entry_type)
         {
-          gboolean  ret;
-          char     *file_id;
+          gboolean    ret;
+          char       *file_id;
+          const char *basename;
 
-          g_string_append (relative_path,
-                           desktop_entry_get_basename (entry));
+          basename = desktop_entry_get_basename (entry);
+          g_string_append (relative_path, basename);
 
 	  file_id = get_desktop_file_id_from_path (ed,
 						   ed->entry_type,
@@ -874,7 +914,7 @@ entry_directory_foreach_recursive (Entry
       CachedDir *subdir = tmp->data;
 
       g_string_append (relative_path, subdir->name);
-      g_string_append_c (relative_path, '/');
+      g_string_append_c (relative_path, G_DIR_SEPARATOR);
 
       if (!entry_directory_foreach_recursive (ed,
                                               subdir,
@@ -929,7 +969,7 @@ entry_directory_get_flat_contents (Entry
       DesktopEntry *entry = tmp->data;
       const char   *basename;
 
-      basename = desktop_entry_get_basename (entry);
+      basename = desktop_entry_get_path (entry);
 
       if (desktop_entries &&
           desktop_entry_get_type (entry) == DESKTOP_ENTRY_DESKTOP)
@@ -1002,7 +1042,7 @@ entry_directory_list_ref (EntryDirectory
   g_return_val_if_fail (list != NULL, NULL);
   g_return_val_if_fail (list->refcount > 0, NULL);
 
-  list->refcount += 1;
+  g_atomic_int_inc (&list->refcount);
 
   return list;
 }
@@ -1010,11 +1050,13 @@ entry_directory_list_ref (EntryDirectory
 void
 entry_directory_list_unref (EntryDirectoryList *list)
 {
+  gboolean is_zero;
+
   g_return_if_fail (list != NULL);
   g_return_if_fail (list->refcount > 0);
 
-  list->refcount -= 1;
-  if (list->refcount == 0)
+  is_zero = g_atomic_int_dec_and_test (&list->refcount);
+  if (is_zero)
     {
       g_list_foreach (list->dirs, (GFunc) entry_directory_unref, NULL);
       g_list_free (list->dirs);
Index: libmenu/gmenu-tree.c
===================================================================
RCS file: /cvs/gnome/gnome-menus/libmenu/gmenu-tree.c,v
retrieving revision 1.41
diff -p -u -r1.41 gmenu-tree.c
--- libmenu/gmenu-tree.c	5 May 2006 15:27:07 -0000	1.41
+++ libmenu/gmenu-tree.c	2 Aug 2006 18:45:41 -0000
@@ -44,7 +44,7 @@ typedef enum
 struct GMenuTree
 {
   GMenuTreeType type;
-  guint         refcount;
+  volatile gint refcount;
 
   char *basename;
   char *absolute_path;
@@ -76,11 +76,11 @@ struct GMenuTreeItem
   GMenuTreeItemType type;
 
   GMenuTreeDirectory *parent;
-  
+
   gpointer       user_data;
   GDestroyNotify dnotify;
 
-  guint refcount;
+  volatile gint refcount;
 };
 
 struct GMenuTreeDirectory
@@ -154,7 +154,7 @@ static void      gmenu_tree_resolve_file
 						  MenuLayoutNode  *layout);
 static void      gmenu_tree_force_recanonicalize (GMenuTree       *tree);
 static void      gmenu_tree_invoke_monitors      (GMenuTree       *tree);
-     
+
 static void gmenu_tree_item_unref_and_unset_parent (gpointer itemp);
 
 /*
@@ -229,6 +229,7 @@ gmenu_tree_remove_from_cache (GMenuTree 
 
   if (g_hash_table_size (gmenu_tree_cache) == 0)
     {
+      menu_verbose ("Destroying cache\n");
       g_hash_table_destroy (gmenu_tree_cache);
       gmenu_tree_cache = NULL;
     }
@@ -653,7 +654,7 @@ gmenu_tree_ref (GMenuTree *tree)
   g_return_val_if_fail (tree != NULL, NULL);
   g_return_val_if_fail (tree->refcount > 0, NULL);
 
-  tree->refcount++;
+  g_atomic_int_inc (&tree->refcount);
 
   return tree;
 }
@@ -661,10 +662,14 @@ gmenu_tree_ref (GMenuTree *tree)
 void
 gmenu_tree_unref (GMenuTree *tree)
 {
+  gboolean is_zero;
+
   g_return_if_fail (tree != NULL);
-  g_return_if_fail (tree->refcount >= 1);
+  g_return_if_fail (tree->refcount > 0);
 
-  if (--tree->refcount > 0)
+  is_zero = g_atomic_int_dec_and_test (&tree->refcount);
+
+  if (G_UNLIKELY (!is_zero))
     return;
 
   if (tree->dnotify)
@@ -1063,8 +1068,12 @@ gmenu_tree_directory_make_path (GMenuTre
   append_directory_path (directory, path);
 
   if (entry != NULL)
-    g_string_append (path,
-		     desktop_entry_get_basename (entry->desktop_entry));
+    {
+      const char *basename;
+
+      basename = desktop_entry_get_basename (entry->desktop_entry);
+      g_string_append (path, basename);
+    }
 
   return g_string_free (path, FALSE);
 }
@@ -1104,7 +1113,7 @@ gmenu_tree_entry_get_exec (GMenuTreeEntr
 gboolean
 gmenu_tree_entry_get_launch_in_terminal (GMenuTreeEntry *entry)
 {
-  g_return_val_if_fail (entry != NULL, NULL);
+  g_return_val_if_fail (entry != NULL, FALSE);
 
   return desktop_entry_get_launch_in_terminal (entry->desktop_entry);
 }
@@ -1229,7 +1238,7 @@ gmenu_tree_directory_finalize (GMenuTree
 		   NULL);
   g_slist_free (directory->contents);
   directory->contents = NULL;
-  
+
   g_slist_foreach (directory->default_layout_info,
 		   (GFunc) menu_layout_node_unref,
 		   NULL);
@@ -1409,13 +1418,13 @@ gpointer
 gmenu_tree_item_ref (gpointer itemp)
 {
   GMenuTreeItem *item;
-  
+
   item = (GMenuTreeItem *) itemp;
 
   g_return_val_if_fail (item != NULL, NULL);
   g_return_val_if_fail (item->refcount > 0, NULL);
 
-  item->refcount++;
+  g_atomic_int_inc (&item->refcount);
 
   return item;
 }
@@ -1424,13 +1433,16 @@ void
 gmenu_tree_item_unref (gpointer itemp)
 {
   GMenuTreeItem *item;
+  gboolean       is_zero;
 
   item = (GMenuTreeItem *) itemp;
 
   g_return_if_fail (item != NULL);
   g_return_if_fail (item->refcount > 0);
 
-  if (--item->refcount == 0)
+  is_zero = g_atomic_int_dec_and_test (&item->refcount);
+
+  if (G_LIKELY (is_zero))
     {
       switch (item->type)
 	{
Index: libmenu/menu-monitor.c
===================================================================
RCS file: /cvs/gnome/gnome-menus/libmenu/menu-monitor.c,v
retrieving revision 1.9
diff -p -u -r1.9 menu-monitor.c
--- libmenu/menu-monitor.c	29 Jan 2006 17:57:12 -0000	1.9
+++ libmenu/menu-monitor.c	2 Aug 2006 18:45:41 -0000
@@ -284,6 +284,14 @@ menu_monitor_unref (MenuMonitor *monitor
   g_hash_table_remove (monitors_registry, registry_key);
   g_free (registry_key);
 
+  if (g_hash_table_size (monitors_registry) == 0)
+    {
+      menu_verbose ("Destroying monitors registry\n");
+
+      g_hash_table_destroy (monitors_registry);
+      monitors_registry = NULL;
+    }
+
   menu_monitor_backend_unregister_monitor (monitor);
 
   g_slist_foreach (monitor->notifies, (GFunc) menu_monitor_notify_unref, NULL);
