emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Using glib's g_file_monitor_file and g_file_monitor_directory


From: Paul Eggert
Subject: Re: Using glib's g_file_monitor_file and g_file_monitor_directory
Date: Mon, 03 Jun 2013 23:45:30 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130510 Thunderbird/17.0.6

A quick review of some of the C-level changes:

* The XIL ((EMACS_INT) monitor) trick doesn't work in
  general, since the monitor address could look like a
  tagged Emacs object and the garbage collector could
  go kaflooey on it.  Instead, perhaps use make_save_pointer,
  as it's designed for this sort of thing.

* Faster and simpler than FUNCTIONP (CDR_SAFE (watch_object))
  is CONSP (watch_object).  Since the user can't modify
  the watch list we can rely on it to be a list of pairs.

* report_file_error reads errno, so it's not suitable
  when errno's value is indeterminate.  
  xsignal... (Qfile_error, ...) is preferable.

Maybe something like the following patch?  I couldn't get
this stuff to work on my Fedora 17 host, either without or
with the patch, but it should be necessary to apply something
like the following.

=== modified file 'src/gfilenotify.c'
--- src/gfilenotify.c   2013-06-03 13:03:05 +0000
+++ src/gfilenotify.c   2013-06-04 06:43:23 +0000
@@ -95,21 +95,26 @@ dir_monitor_callback (GFileMonitor* moni
     }
 
   /* Determine callback function.  */
-  watch_object = Fassoc (XIL ((EMACS_INT) monitor), watch_list);
+  for (watch_object = watch_list;
+       CONSP (watch_object);
+       watch_object = XCDR (watch_object))
+    if (XSAVE_POINTER (XCAR (watch_object), 0) == monitor)
+      break;
 
-  if (FUNCTIONP (CDR_SAFE (watch_object)))
+  if (CONSP (watch_object))
     {
       /* Construct an event.  */
       struct input_event event;
       EVENT_INIT (event);
       event.kind = FILE_NOTIFY_EVENT;
       event.frame_or_window = Qnil;
-      event.arg = oname
-       ? list2 (list4 (XIL ((EMACS_INT) monitor), symbol,
-                       build_string (name), build_string (oname)),
-                CDR_SAFE (watch_object))
-       : list2 (list3 (XIL ((EMACS_INT) monitor), symbol, build_string (name)),
-                CDR_SAFE (watch_object));
+      event.arg = list2 (Fcons (XCAR (watch_object),
+                               Fcons (symbol,
+                                      Fcons (build_string (name),
+                                             (oname
+                                              ? list1 (build_string (oname))
+                                              : Qnil)))),
+                        XCDR (watch_object));
 
       /* Store it into the input event queue.  */
       kbd_buffer_store_event (&event);
@@ -194,10 +199,10 @@ will be reported only in case of the 'mo
     g_signal_connect (monitor, "changed",
                      (GCallback) dir_monitor_callback, NULL);
   else
-    report_file_error ("Cannot watch file", Fcons (file, Qnil));
+    xsignal2 (Qfile_error, build_string ("Cannot watch file"), file);
 
   /* Store watch object in watch list.  */
-  watch_descriptor = XIL ((EMACS_INT) monitor);
+  watch_descriptor = make_save_pointer (monitor);
   watch_object = Fcons (watch_descriptor, callback);
   watch_list = Fcons (watch_object, watch_list);
 
@@ -210,20 +215,20 @@ DEFUN ("gfile-rm-watch", Fgfile_rm_watch
 WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'.  */)
      (Lisp_Object watch_descriptor)
 {
-  Lisp_Object watch_object;
-  GFileMonitor *monitor = (GFileMonitor *) XLI (watch_descriptor);
+  GFileMonitor *monitor;
+  Lisp_Object watch_object = Fassq (watch_descriptor, watch_list);
 
-  watch_object = Fassoc (watch_descriptor, watch_list);
-  if (NILP (watch_object))
-    report_file_error ("Not a watch descriptor",
-                      Fcons (watch_descriptor, Qnil));
+  if (! CONSP (watch_object))
+    xsignal2 (Qfile_error, build_string ("Not a watch descriptor"),
+             watch_descriptor);
 
+  monitor = XSAVE_POINTER (XCAR (watch_object), 0);
   if (!g_file_monitor_cancel (monitor))
-    report_file_error ("Could not rm watch",
-                      Fcons (watch_descriptor, Qnil));
+    xsignal2 (Qfile_error, build_string ("Could not rm watch"),
+             watch_descriptor);
 
   /* Remove watch descriptor from watch list. */
-  watch_list = Fdelete (watch_object, watch_list);
+  watch_list = Fdelq (watch_object, watch_list);
 
   /* Cleanup.  */
   g_object_unref (monitor);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]