Author: benny
Date: 2006-09-13 21:40:25 +0000 (Wed, 13 Sep 2006)
New Revision: 23149

Modified:
   thunar/trunk/ChangeLog
   thunar/trunk/thunar-vfs/thunar-vfs-monitor.c
   thunar/trunk/thunar/thunar-file.c
   thunar/trunk/thunar/thunar-standard-view.c
Log:
2006-09-13      Benedikt Meurer <[EMAIL PROTECTED]>

        * thunar-vfs/thunar-vfs-monitor.c, thunar/thunar-standard-view.c:
          Fix several race conditions that were introduced over time and
          prevented the "new-files" job handling from working properly with
          Gamin and automatic folder reload. Bug #2199.
        * thunar/thunar-file.c: The file must not be dropped from the hash
          table in the dispose() function, but only when finalize is called,
          because dispose() may be invoked more than once and hence we might
          drop a newly created ThunarFile object with the same path from
          the hash table.




Modified: thunar/trunk/ChangeLog
===================================================================
--- thunar/trunk/ChangeLog      2006-09-13 21:38:40 UTC (rev 23148)
+++ thunar/trunk/ChangeLog      2006-09-13 21:40:25 UTC (rev 23149)
@@ -1,5 +1,17 @@
 2006-09-13     Benedikt Meurer <[EMAIL PROTECTED]>
 
+       * thunar-vfs/thunar-vfs-monitor.c, thunar/thunar-standard-view.c:
+         Fix several race conditions that were introduced over time and
+         prevented the "new-files" job handling from working properly with
+         Gamin and automatic folder reload. Bug #2199.
+       * thunar/thunar-file.c: The file must not be dropped from the hash
+         table in the dispose() function, but only when finalize is called,
+         because dispose() may be invoked more than once and hence we might
+         drop a newly created ThunarFile object with the same path from
+         the hash table.
+
+2006-09-13     Benedikt Meurer <[EMAIL PROTECTED]>
+
        * configure.in.in, Makefile.am: Place automake options into
          configure.in.in instead of Makefile.am and add the tar-ustar
          option to fix building distributions on system where tar defaults

Modified: thunar/trunk/thunar/thunar-file.c
===================================================================
--- thunar/trunk/thunar/thunar-file.c   2006-09-13 21:38:40 UTC (rev 23148)
+++ thunar/trunk/thunar/thunar-file.c   2006-09-13 21:40:25 UTC (rev 23149)
@@ -299,9 +299,6 @@
       file->flags &= ~THUNAR_FILE_IN_DESTRUCTION;
     }
 
-  /* drop the entry from the cache */
-  g_hash_table_remove (file_cache, file->info->path);
-
   (*G_OBJECT_CLASS (thunar_file_parent_class)->dispose) (object);
 }
 
@@ -321,6 +318,9 @@
     }
 #endif
 
+  /* drop the entry from the cache */
+  g_hash_table_remove (file_cache, file->info->path);
+
   /* drop a reference on the metadata if we own one */
   if ((file->flags & THUNAR_FILE_OWNS_METAFILE_REFERENCE) != 0)
     g_object_unref (G_OBJECT (metafile));

Modified: thunar/trunk/thunar/thunar-standard-view.c
===================================================================
--- thunar/trunk/thunar/thunar-standard-view.c  2006-09-13 21:38:40 UTC (rev 
23148)
+++ thunar/trunk/thunar/thunar-standard-view.c  2006-09-13 21:40:25 UTC (rev 
23149)
@@ -187,9 +187,8 @@
 static void                 thunar_standard_view_action_restore             
(GtkAction                *action,
                                                                              
ThunarStandardView       *standard_view);
 static GClosure            *thunar_standard_view_new_files_closure          
(ThunarStandardView       *standard_view);
-static void                 thunar_standard_view_new_files                  
(ThunarVfsJob             *job,
-                                                                             
GList                    *path_list,
-                                                                             
ThunarStandardView       *standard_view);
+static void                 thunar_standard_view_new_files                  
(ThunarStandardView       *standard_view,
+                                                                             
GList                    *path_list);
 static gboolean             thunar_standard_view_button_release_event       
(GtkWidget                *view,
                                                                              
GdkEventButton           *event,
                                                                              
ThunarStandardView       *standard_view);
@@ -299,6 +298,14 @@
    */
   GClosure               *new_files_closure;
 
+  /* the "new-files" path list that was remember in the closure callback
+   * if the view is currently being loaded and as such the folder may
+   * not have all "new-files" at hand. This list is used when the
+   * folder tells that it's ready loading and the view will try again
+   * to select exactly this files.
+   */
+  GList                  *new_files_path_list;
+
   /* scroll-to-file support */
   ThunarFile             *scroll_to_file;
   guint                   scroll_to_select : 1;
@@ -758,6 +765,9 @@
       standard_view->priv->new_files_closure = NULL;
     }
 
+  /* drop any remaining "new-files" paths */
+  thunar_vfs_path_list_free (standard_view->priv->new_files_path_list);
+
   /* release our reference on the preferences */
   g_object_unref (G_OBJECT (standard_view->preferences));
 
@@ -1205,6 +1215,7 @@
                                   gboolean            loading)
 {
   ThunarFile *file;
+  GList      *new_files_path_list;
 
   loading = !!loading;
 
@@ -1233,6 +1244,20 @@
       g_object_unref (G_OBJECT (file));
     }
 
+  /* check if we have a path list from new_files pending */
+  if (G_UNLIKELY (!loading && standard_view->priv->new_files_path_list != 
NULL))
+    {
+      /* remember and reset the new_files_path_list */
+      new_files_path_list = standard_view->priv->new_files_path_list;
+      standard_view->priv->new_files_path_list = NULL;
+
+      /* and try again */
+      thunar_standard_view_new_files (standard_view, new_files_path_list);
+
+      /* cleanup */
+      thunar_vfs_path_list_free (new_files_path_list);
+    }
+
   /* notify listeners */
   g_object_freeze_notify (G_OBJECT (standard_view));
   g_object_notify (G_OBJECT (standard_view), "loading");
@@ -2309,7 +2334,7 @@
     }
 
   /* allocate a new "new-files" closure */
-  standard_view->priv->new_files_closure = g_cclosure_new (G_CALLBACK 
(thunar_standard_view_new_files), standard_view, NULL);
+  standard_view->priv->new_files_closure = g_cclosure_new_swap (G_CALLBACK 
(thunar_standard_view_new_files), standard_view, NULL);
   g_closure_ref (standard_view->priv->new_files_closure);
   g_closure_sink (standard_view->priv->new_files_closure);
 
@@ -2320,40 +2345,50 @@
 
 
 static void
-thunar_standard_view_new_files (ThunarVfsJob       *job,
-                                GList              *path_list,
-                                ThunarStandardView *standard_view)
+thunar_standard_view_new_files (ThunarStandardView *standard_view,
+                                GList              *path_list)
 {
   ThunarFile*file;
   GList     *file_list = NULL;
   GList     *lp;
 
-  _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job));
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
 
-  /* verify that we have a non-empty path_list */
-  if (G_UNLIKELY (path_list == NULL))
-    return;
-
-  /* determine the files for the paths */
-  for (lp = path_list; lp != NULL; lp = lp->next)
+  /* release the previous "new-files" paths (if any) */
+  if (G_UNLIKELY (standard_view->priv->new_files_path_list != NULL))
     {
-      file = thunar_file_cache_lookup (lp->data);
-      if (G_LIKELY (file != NULL))
-        file_list = g_list_prepend (file_list, file);
+      thunar_vfs_path_list_free (standard_view->priv->new_files_path_list);
+      standard_view->priv->new_files_path_list = NULL;
     }
 
-  /* check if we have any new files here */
-  if (G_LIKELY (file_list != NULL))
+  /* check if the folder is currently being loaded */
+  if (G_UNLIKELY (standard_view->loading))
     {
-      /* select the files */
-      thunar_component_set_selected_files (THUNAR_COMPONENT (standard_view), 
file_list);
+      /* schedule the "new-files" paths for later processing */
+      standard_view->priv->new_files_path_list = thunar_vfs_path_list_copy 
(path_list);
+    }
+  else if (G_LIKELY (path_list != NULL))
+    {
+      /* determine the files for the paths */
+      for (lp = path_list; lp != NULL; lp = lp->next)
+        {
+          file = thunar_file_cache_lookup (lp->data);
+          if (G_LIKELY (file != NULL))
+            file_list = g_list_prepend (file_list, file);
+        }
 
-      /* release the file list */
-      g_list_free (file_list);
+      /* check if we have any new files here */
+      if (G_LIKELY (file_list != NULL))
+        {
+          /* select the files */
+          thunar_component_set_selected_files (THUNAR_COMPONENT 
(standard_view), file_list);
 
-      /* grab the focus to the view widget */
-      gtk_widget_grab_focus (GTK_BIN (standard_view)->child);
+          /* release the file list */
+          g_list_free (file_list);
+
+          /* grab the focus to the view widget */
+          gtk_widget_grab_focus (GTK_BIN (standard_view)->child);
+        }
     }
 }
 

Modified: thunar/trunk/thunar-vfs/thunar-vfs-monitor.c
===================================================================
--- thunar/trunk/thunar-vfs/thunar-vfs-monitor.c        2006-09-13 21:38:40 UTC 
(rev 23148)
+++ thunar/trunk/thunar-vfs/thunar-vfs-monitor.c        2006-09-13 21:40:25 UTC 
(rev 23149)
@@ -39,9 +39,12 @@
 
 
 
-/* minimum timer interval (in ms) */
-#define THUNAR_VFS_MONITOR_TIMER_INTERVAL (200)
+/* minimum timer interval for feeded events (in ms) */
+#define THUNAR_VFS_MONITOR_TIMER_INTERVAL_FEED (10)
 
+/* minimum timer interval for FAM events (in ms) */
+#define THUNAR_VFS_MONITOR_TIMER_INTERVAL_FAM (200)
+
 /* tagging for notifications, so we can make sure that
  * (slow) FAM events don't override properly feeded events.
  */
@@ -171,7 +174,6 @@
 thunar_vfs_monitor_init (ThunarVfsMonitor *monitor)
 {
   /* initialize the monitor */
-  monitor->notifications_timer_id = -1;
   monitor->cond = g_cond_new ();
   monitor->lock = g_mutex_new ();
 
@@ -212,7 +214,7 @@
 #endif
 
   /* drop the notifications timer source */
-  if (G_UNLIKELY (monitor->notifications_timer_id >= 0))
+  if (G_UNLIKELY (monitor->notifications_timer_id != 0))
     g_source_remove (monitor->notifications_timer_id);
 
   /* drop all pending notifications */
@@ -249,22 +251,17 @@
                                        const gchar          *filename)
 {
   ThunarVfsMonitorNotification *notification;
+  ThunarVfsMonitorNotification *position;
+  guint                         timeout;
   gint                          length;
 
-  g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor));
-  g_return_if_fail (reqnum > 0 && reqnum <= monitor->current_reqnum);
+  _thunar_vfs_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor));
+  _thunar_vfs_return_if_fail (reqnum > 0 && reqnum <= monitor->current_reqnum);
 
   /* check if we already have a matching notification */
   for (notification = monitor->notifications; notification != NULL; 
notification = notification->next)
-    if (notification->reqnum == reqnum && exo_str_is_equal (filename, 
notification->filename))
-      {
-        if (tag >= notification->tag)
-          {
-            notification->tag = tag;
-            notification->event = event;
-          }
-        return;
-      }
+    if (notification->reqnum == reqnum && exo_str_is_equal (filename, 
notification->filename) && notification->tag == tag && notification->event == 
event)
+      return;
 
   /* allocate a new notification */
   if (G_LIKELY (filename != NULL))
@@ -280,16 +277,40 @@
       notification->filename = NULL;
     }
 
-  /* prepend the notification to the queue */
+  /* prepare the notification */
   notification->reqnum = reqnum;
   notification->tag = tag;
-  notification->next = monitor->notifications;
   notification->event = event;
-  monitor->notifications = notification;
 
+  /* and append it to the list */
+  if (monitor->notifications == NULL)
+    {
+      /* we have a new head */
+      monitor->notifications = notification;
+      notification->next = NULL;
+    }
+  else
+    {
+      /* lookup the position where to insert the notification, making sure 
that FAM events will be sorted after feeded ones... */
+      for (position = monitor->notifications; position->next != NULL && 
position->tag >= tag; position = position->next)
+        ;
+
+      /* ...and insert the notification */
+      notification->next = position->next;
+      position->next = notification;
+    }
+
   /* schedule the notification timer if not already active */
-  if (G_UNLIKELY (monitor->notifications_timer_id < 0))
-    monitor->notifications_timer_id = g_timeout_add 
(THUNAR_VFS_MONITOR_TIMER_INTERVAL, thunar_vfs_monitor_notifications_timer, 
monitor);
+  if (G_UNLIKELY (monitor->notifications_timer_id == 0))
+    {
+      /* use a shorter timeout for feeded events */
+      timeout = (tag == THUNAR_VFS_MONITOR_TAG_FEED)
+              ? THUNAR_VFS_MONITOR_TIMER_INTERVAL_FEED
+              : THUNAR_VFS_MONITOR_TIMER_INTERVAL_FAM;
+
+      /* schedule the timer source with the timeout */
+      monitor->notifications_timer_id = g_timeout_add (timeout, 
thunar_vfs_monitor_notifications_timer, monitor);
+    }
 }
 
 
@@ -312,7 +333,7 @@
   g_mutex_lock (monitor->lock);
 
   /* reset the timer id */
-  monitor->notifications_timer_id = -1;
+  monitor->notifications_timer_id = 0;
 
   /* process all pending notifications */
   while (monitor->notifications != NULL)
@@ -374,8 +395,8 @@
 static void
 thunar_vfs_monitor_fam_cancel (ThunarVfsMonitor *monitor)
 {
-  g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor));
-  g_return_if_fail (monitor->fc_watch_id >= 0);
+  _thunar_vfs_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor));
+  _thunar_vfs_return_if_fail (monitor->fc_watch_id >= 0);
 
   /* close the FAM connection */
   FAMClose (&monitor->fc);
@@ -704,7 +725,7 @@
   g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor));
 
   g_mutex_lock (monitor->lock);
-  while (g_atomic_int_get (&monitor->notifications_timer_id) >= 0)
+  while (g_atomic_int_get (&monitor->notifications_timer_id) != 0)
     g_cond_timed_wait (monitor->cond, monitor->lock, (GTimeVal *) &tv);
   g_mutex_unlock (monitor->lock);
 }

_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to