aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2015-11-09 20:26:10 +0100
committerMichael Albinus2015-11-11 12:10:48 +0100
commit0198c3066e8866d464690a9a7924d42e9c2663bf (patch)
treef0b6e7771a4372da7a6476984e0d401974c9c3ca
parent662ee733257d573deaadd2e217894b70265fb5fe (diff)
downloademacs-0198c3066e8866d464690a9a7924d42e9c2663bf.tar.gz
emacs-0198c3066e8866d464690a9a7924d42e9c2663bf.zip
Work on kqueue
* lisp/filenotify.el (file-notify--library) (file-notify-descriptors, file-notify-callback) (file-notify-add-watch, file-notify-rm-watch) (file-notify-valid-p): Add kqueue support. * src/keyboard.c (make_lispy_event): Check also for HAVE_KQUEUE.
-rw-r--r--lisp/filenotify.el40
-rw-r--r--src/keyboard.c4
-rw-r--r--src/kqueue.c270
3 files changed, 125 insertions, 189 deletions
diff --git a/lisp/filenotify.el b/lisp/filenotify.el
index 4c5d43fb44e..f7c97569825 100644
--- a/lisp/filenotify.el
+++ b/lisp/filenotify.el
@@ -22,15 +22,16 @@
22;;; Commentary 22;;; Commentary
23 23
24;; This package is an abstraction layer from the different low-level 24;; This package is an abstraction layer from the different low-level
25;; file notification packages `gfilenotify', `inotify' and 25;; file notification packages `inotify', `kqueue', `gfilenotify' and
26;; `w32notify'. 26;; `w32notify'.
27 27
28;;; Code: 28;;; Code:
29 29
30(defconst file-notify--library 30(defconst file-notify--library
31 (cond 31 (cond
32 ((featurep 'gfilenotify) 'gfilenotify)
33 ((featurep 'inotify) 'inotify) 32 ((featurep 'inotify) 'inotify)
33 ((featurep 'kqueue) 'kqueue)
34 ((featurep 'gfilenotify) 'gfilenotify)
34 ((featurep 'w32notify) 'w32notify)) 35 ((featurep 'w32notify) 'w32notify))
35 "Non-nil when Emacs has been compiled with file notification support. 36 "Non-nil when Emacs has been compiled with file notification support.
36The value is the name of the low-level file notification package 37The value is the name of the low-level file notification package
@@ -40,8 +41,8 @@ could use another implementation.")
40(defvar file-notify-descriptors (make-hash-table :test 'equal) 41(defvar file-notify-descriptors (make-hash-table :test 'equal)
41 "Hash table for registered file notification descriptors. 42 "Hash table for registered file notification descriptors.
42A key in this hash table is the descriptor as returned from 43A key in this hash table is the descriptor as returned from
43`gfilenotify', `inotify', `w32notify' or a file name handler. 44`inotify', `kqueue', `gfilenotify', `w32notify' or a file name
44The value in the hash table is a list 45handler. The value in the hash table is a list
45 46
46 (DIR (FILE . CALLBACK) (FILE . CALLBACK) ...) 47 (DIR (FILE . CALLBACK) (FILE . CALLBACK) ...)
47 48
@@ -76,7 +77,8 @@ WHAT is a file or directory name to be removed, needed just for `inotify'."
76 (remhash desc file-notify-descriptors) 77 (remhash desc file-notify-descriptors)
77 (puthash desc registered file-notify-descriptors)))))) 78 (puthash desc registered file-notify-descriptors))))))
78 79
79;; This function is used by `gfilenotify', `inotify' and `w32notify' events. 80;; This function is used by `inotify', `kqueue', `gfilenotify' and
81;; `w32notify' events.
80;;;###autoload 82;;;###autoload
81(defun file-notify-handle-event (event) 83(defun file-notify-handle-event (event)
82 "Handle file system monitoring event. 84 "Handle file system monitoring event.
@@ -159,7 +161,7 @@ EVENT is the cadr of the event in `file-notify-handle-event'
159 (setq actions nil)) 161 (setq actions nil))
160 162
161 ;; Loop over actions. In fact, more than one action happens only 163 ;; Loop over actions. In fact, more than one action happens only
162 ;; for `inotify'. 164 ;; for `inotify' and `kqueue'.
163 (dolist (action actions) 165 (dolist (action actions)
164 166
165 ;; Send pending event, if it doesn't match. 167 ;; Send pending event, if it doesn't match.
@@ -184,19 +186,17 @@ EVENT is the cadr of the event in `file-notify-handle-event'
184 ;; Map action. We ignore all events which cannot be mapped. 186 ;; Map action. We ignore all events which cannot be mapped.
185 (setq action 187 (setq action
186 (cond 188 (cond
187 ;; gfilenotify. 189 ((memq action
188 ((memq action '(attribute-changed changed created deleted)) 190 '(attribute-changed changed created deleted renamed))
189 action) 191 action)
190 ((eq action 'moved) 192 ((eq action 'moved)
191 (setq file1 (file-notify--event-file1-name event)) 193 (setq file1 (file-notify--event-file1-name event))
192 'renamed) 194 'renamed)
193
194 ;; inotify, w32notify.
195 ((eq action 'ignored) 195 ((eq action 'ignored)
196 (setq stopped t actions nil)) 196 (setq stopped t actions nil))
197 ((eq action 'attrib) 'attribute-changed) 197 ((memq action '(attrib link)) 'attribute-changed)
198 ((memq action '(create added)) 'created) 198 ((memq action '(create added)) 'created)
199 ((memq action '(modify modified)) 'changed) 199 ((memq action '(modify modified write)) 'changed)
200 ((memq action '(delete delete-self move-self removed)) 'deleted) 200 ((memq action '(delete delete-self move-self removed)) 'deleted)
201 ;; Make the event pending. 201 ;; Make the event pending.
202 ((memq action '(moved-from renamed-from)) 202 ((memq action '(moved-from renamed-from))
@@ -275,8 +275,8 @@ EVENT is the cadr of the event in `file-notify-handle-event'
275 (file-notify--rm-descriptor 275 (file-notify--rm-descriptor
276 (file-notify--descriptor desc file) file))))) 276 (file-notify--descriptor desc file) file)))))
277 277
278;; `gfilenotify' and `w32notify' return a unique descriptor for every 278;; `kqueue', `gfilenotify' and `w32notify' return a unique descriptor
279;; `file-notify-add-watch', while `inotify' returns a unique 279;; for every `file-notify-add-watch', while `inotify' returns a unique
280;; descriptor per inode only. 280;; descriptor per inode only.
281(defun file-notify-add-watch (file flags callback) 281(defun file-notify-add-watch (file flags callback)
282 "Add a watch for filesystem events pertaining to FILE. 282 "Add a watch for filesystem events pertaining to FILE.
@@ -349,8 +349,9 @@ FILE is the name of the file whose event is being reported."
349 ;; Determine low-level function to be called. 349 ;; Determine low-level function to be called.
350 (setq func 350 (setq func
351 (cond 351 (cond
352 ((eq file-notify--library 'gfilenotify) 'gfile-add-watch)
353 ((eq file-notify--library 'inotify) 'inotify-add-watch) 352 ((eq file-notify--library 'inotify) 'inotify-add-watch)
353 ((eq file-notify--library 'kqueue) 'kqueue-add-watch)
354 ((eq file-notify--library 'gfilenotify) 'gfile-add-watch)
354 ((eq file-notify--library 'w32notify) 'w32notify-add-watch))) 355 ((eq file-notify--library 'w32notify) 'w32notify-add-watch)))
355 356
356 ;; Determine respective flags. 357 ;; Determine respective flags.
@@ -362,11 +363,14 @@ FILE is the name of the file whose event is being reported."
362 (cond 363 (cond
363 ((eq file-notify--library 'inotify) 364 ((eq file-notify--library 'inotify)
364 '(create delete delete-self modify move-self move)) 365 '(create delete delete-self modify move-self move))
366 ((eq file-notify--library 'kqueue)
367 '(delete write extend rename))
365 ((eq file-notify--library 'w32notify) 368 ((eq file-notify--library 'w32notify)
366 '(file-name directory-name size last-write-time))))) 369 '(file-name directory-name size last-write-time)))))
367 (when (memq 'attribute-change flags) 370 (when (memq 'attribute-change flags)
368 (push (cond 371 (push (cond
369 ((eq file-notify--library 'inotify) 'attrib) 372 ((eq file-notify--library 'inotify) 'attrib)
373 ((eq file-notify--library 'kqueue) 'attrib)
370 ((eq file-notify--library 'w32notify) 'attributes)) 374 ((eq file-notify--library 'w32notify) 'attributes))
371 l-flags))) 375 l-flags)))
372 376
@@ -410,8 +414,9 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'."
410 414
411 (funcall 415 (funcall
412 (cond 416 (cond
413 ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch)
414 ((eq file-notify--library 'inotify) 'inotify-rm-watch) 417 ((eq file-notify--library 'inotify) 'inotify-rm-watch)
418 ((eq file-notify--library 'kqueue) 'kqueue-rm-watch)
419 ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch)
415 ((eq file-notify--library 'w32notify) 'w32notify-rm-watch)) 420 ((eq file-notify--library 'w32notify) 'w32notify-rm-watch))
416 desc)) 421 desc))
417 (file-notify-error nil))) 422 (file-notify-error nil)))
@@ -441,8 +446,9 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'."
441 (funcall handler 'file-notify-valid-p descriptor) 446 (funcall handler 'file-notify-valid-p descriptor)
442 (funcall 447 (funcall
443 (cond 448 (cond
444 ((eq file-notify--library 'gfilenotify) 'gfile-valid-p)
445 ((eq file-notify--library 'inotify) 'inotify-valid-p) 449 ((eq file-notify--library 'inotify) 'inotify-valid-p)
450 ((eq file-notify--library 'kqueue) 'kqueue-valid-p)
451 ((eq file-notify--library 'gfilenotify) 'gfile-valid-p)
446 ((eq file-notify--library 'w32notify) 'w32notify-valid-p)) 452 ((eq file-notify--library 'w32notify) 'w32notify-valid-p))
447 desc)) 453 desc))
448 t)))) 454 t))))
diff --git a/src/keyboard.c b/src/keyboard.c
index 851207874db..a6ada2106fb 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5951,12 +5951,12 @@ make_lispy_event (struct input_event *event)
5951 } 5951 }
5952#endif /* HAVE_DBUS */ 5952#endif /* HAVE_DBUS */
5953 5953
5954#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY 5954#if defined HAVE_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY
5955 case FILE_NOTIFY_EVENT: 5955 case FILE_NOTIFY_EVENT:
5956 { 5956 {
5957 return Fcons (Qfile_notify, event->arg); 5957 return Fcons (Qfile_notify, event->arg);
5958 } 5958 }
5959#endif /* defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY */ 5959#endif /* HAVE_INOTIFY || HAVE_KQUEUE || HAVE_GFILENOTIFY */
5960 5960
5961 case CONFIG_CHANGED_EVENT: 5961 case CONFIG_CHANGED_EVENT:
5962 return list3 (Qconfig_changed_event, 5962 return list3 (Qconfig_changed_event,
diff --git a/src/kqueue.c b/src/kqueue.c
index 69bf5f61080..a4c3892e9f2 100644
--- a/src/kqueue.c
+++ b/src/kqueue.c
@@ -21,10 +21,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21#ifdef HAVE_KQUEUE 21#ifdef HAVE_KQUEUE
22#include <stdio.h> 22#include <stdio.h>
23#include <sys/event.h> 23#include <sys/event.h>
24#include <sys/file.h>
24#include "lisp.h" 25#include "lisp.h"
25#include "coding.h"
26#include "termhooks.h"
27#include "keyboard.h" 26#include "keyboard.h"
27#include "process.h"
28 28
29 29
30/* File handle for kqueue. */ 30/* File handle for kqueue. */
@@ -33,149 +33,103 @@ static int kqueuefd = -1;
33/* This is a list, elements are triples (DESCRIPTOR FILE FLAGS CALLBACK) */ 33/* This is a list, elements are triples (DESCRIPTOR FILE FLAGS CALLBACK) */
34static Lisp_Object watch_list; 34static Lisp_Object watch_list;
35 35
36#if 0 36/* This is the callback function for arriving input on kqueuefd. It
37/* This is the callback function for arriving signals from 37 shall create a Lisp event, and put it into Emacs input queue. */
38 g_file_monitor. It shall create a Lisp event, and put it into 38static void
39 Emacs input queue. */ 39kqueue_callback (int fd, void *data)
40static gboolean
41dir_monitor_callback (GFileMonitor *monitor,
42 GFile *file,
43 GFile *other_file,
44 GFileMonitorEvent event_type,
45 gpointer user_data)
46{ 40{
47 Lisp_Object symbol, monitor_object, watch_object, flags; 41 for (;;) {
48 char *name = g_file_get_parse_name (file); 42 struct kevent kev;
49 char *oname = other_file ? g_file_get_parse_name (other_file) : NULL; 43 struct input_event event;
50 44 Lisp_Object monitor_object, watch_object, name, callback, actions;
51 /* Determine event symbol. */ 45
52 switch (event_type) 46 static const struct timespec nullts = { 0, 0 };
53 { 47 int ret = kevent (kqueuefd, NULL, 0, &kev, 1, NULL);
54 case G_FILE_MONITOR_EVENT_CHANGED: 48 if (ret < 1) {
55 symbol = Qchanged; 49 /* All events read. */
56 break; 50 return;
57 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
58 symbol = Qchanges_done_hint;
59 break;
60 case G_FILE_MONITOR_EVENT_DELETED:
61 symbol = Qdeleted;
62 break;
63 case G_FILE_MONITOR_EVENT_CREATED:
64 symbol = Qcreated;
65 break;
66 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
67 symbol = Qattribute_changed;
68 break;
69 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
70 symbol = Qpre_unmount;
71 break;
72 case G_FILE_MONITOR_EVENT_UNMOUNTED:
73 symbol = Qunmounted;
74 break;
75 case G_FILE_MONITOR_EVENT_MOVED:
76 symbol = Qmoved;
77 break;
78 default:
79 goto cleanup;
80 } 51 }
81 52
82 /* Determine callback function. */ 53 /* Determine file name and callback function. */
83 monitor_object = make_pointer_integer (monitor); 54 monitor_object = make_number (kev.ident);
84 eassert (INTEGERP (monitor_object)); 55 watch_object = assq_no_quit (monitor_object, watch_list);
85 watch_object = assq_no_quit (monitor_object, watch_list);
86 56
87 if (CONSP (watch_object)) 57 if (CONSP (watch_object)) {
88 { 58 name = XCAR (XCDR (watch_object));
89 struct input_event event; 59 callback = XCAR (XCDR (XCDR (XCDR (watch_object))));
90 Lisp_Object otail = oname ? list1 (build_string (oname)) : Qnil; 60 }
91 61 else
92 /* Check, whether event_type is expected. */ 62 continue;
93 flags = XCAR (XCDR (XCDR (watch_object))); 63
94 if ((!NILP (Fmember (Qchange, flags)) && 64 /* Determine event actions. */
95 !NILP (Fmember (symbol, list5 (Qchanged, Qchanges_done_hint, 65 actions = Qnil;
96 Qdeleted, Qcreated, Qmoved)))) || 66 if (kev.fflags & NOTE_DELETE)
97 (!NILP (Fmember (Qattribute_change, flags)) && 67 actions = Fcons (Qdelete, actions);
98 ((EQ (symbol, Qattribute_changed))))) 68 if (kev.fflags & NOTE_WRITE)
99 { 69 actions = Fcons (Qwrite, actions);
100 /* Construct an event. */ 70 if (kev.fflags & NOTE_EXTEND)
101 EVENT_INIT (event); 71 actions = Fcons (Qextend, actions);
102 event.kind = FILE_NOTIFY_EVENT; 72 if (kev.fflags & NOTE_ATTRIB)
103 event.frame_or_window = Qnil; 73 actions = Fcons (Qattrib, actions);
104 event.arg = list2 (Fcons (monitor_object, 74 if (kev.fflags & NOTE_LINK)
105 Fcons (symbol, 75 actions = Fcons (Qlink, actions);
106 Fcons (build_string (name), 76 if (kev.fflags & NOTE_RENAME)
107 otail))), 77 actions = Fcons (Qrename, actions);
108 XCAR (XCDR (XCDR (XCDR (watch_object))))); 78
109 79 if (!NILP (actions)) {
110 /* Store it into the input event queue. */ 80 /* Construct an event. */
111 kbd_buffer_store_event (&event); 81 EVENT_INIT (event);
112 // XD_DEBUG_MESSAGE ("%s", XD_OBJECT_TO_STRING (event.arg)); 82 event.kind = FILE_NOTIFY_EVENT;
113 } 83 event.frame_or_window = Qnil;
114 84 event.arg = list2 (Fcons (monitor_object,
115 /* Cancel monitor if file or directory is deleted. */ 85 Fcons (actions, Fcons (name, Qnil))),
116 if (!NILP (Fmember (symbol, list2 (Qdeleted, Qmoved))) && 86 callback);
117 (strcmp (name, SSDATA (XCAR (XCDR (watch_object)))) == 0) && 87
118 !g_file_monitor_is_cancelled (monitor)) 88 /* Store it into the input event queue. */
119 g_file_monitor_cancel (monitor); 89 kbd_buffer_store_event (&event);
120 } 90 }
121 91
122 /* Cleanup. */ 92 /* Cancel monitor if file or directory is deleted. */
123 cleanup: 93 /* TODO: Implement it. */
124 g_free (name); 94 }
125 g_free (oname); 95 return;
126
127 return TRUE;
128} 96}
129#endif /* 0 */
130 97
131DEFUN ("kqueue-add-watch", Fkqueue_add_watch, Skqueue_add_watch, 3, 3, 0, 98DEFUN ("kqueue-add-watch", Fkqueue_add_watch, Skqueue_add_watch, 3, 3, 0,
132 doc: /* Add a watch for filesystem events pertaining to FILE. 99 doc: /* Add a watch for filesystem events pertaining to FILE.
133 100
134This arranges for filesystem events pertaining to FILE to be reported 101This arranges for filesystem events pertaining to FILE to be reported
135to Emacs. Use `gfile-rm-watch' to cancel the watch. 102to Emacs. Use `kqueue-rm-watch' to cancel the watch.
136 103
137Value is a descriptor for the added watch. If the file cannot be 104Value is a descriptor for the added watch. If the file cannot be
138watched for some reason, this function signals a `file-notify-error' error. 105watched for some reason, this function signals a `file-notify-error' error.
139 106
140FLAGS is a list of conditions to set what will be watched for. It can 107FLAGS is a list of events to be watched for. It can include the
141include the following symbols: 108following symbols:
142 109
143 `change' -- watch for file changes 110 `delete' -- FILE was deleted
144 `attribute-change' -- watch for file attributes changes, like 111 `write' -- FILE has changed
145 permissions or modification time 112 `extend' -- FILE was extended
146 `watch-mounts' -- watch for mount events 113 `attrib' -- a FILE attribute was changed
147 `send-moved' -- pair `deleted' and `created' events caused by 114 `link' -- a FILE's link count was changed
148 file renames and send a single `renamed' event 115 `rename' -- FILE was moved to FILE1
149 instead
150 116
151When any event happens, Emacs will call the CALLBACK function passing 117When any event happens, Emacs will call the CALLBACK function passing
152it a single argument EVENT, which is of the form 118it a single argument EVENT, which is of the form
153 119
154 (DESCRIPTOR ACTION FILE [FILE1]) 120 (DESCRIPTOR ACTIONS FILE [FILE1])
155 121
156DESCRIPTOR is the same object as the one returned by this function. 122DESCRIPTOR is the same object as the one returned by this function.
157ACTION is the description of the event. It could be any one of the 123ACTIONS is a list of events.
158following:
159
160 `changed' -- FILE has changed
161 `changes-done-hint' -- a hint that this was probably the last change
162 in a set of changes
163 `deleted' -- FILE was deleted
164 `created' -- FILE was created
165 `attribute-changed' -- a FILE attribute was changed
166 `pre-unmount' -- the FILE location will soon be unmounted
167 `unmounted' -- the FILE location was unmounted
168 `moved' -- FILE was moved to FILE1
169 124
170FILE is the name of the file whose event is being reported. FILE1 125FILE is the name of the file whose event is being reported. FILE1
171will be reported only in case of the `moved' event. */) 126will be reported only in case of the `rename' event. */)
172 (Lisp_Object file, Lisp_Object flags, Lisp_Object callback) 127 (Lisp_Object file, Lisp_Object flags, Lisp_Object callback)
173{ 128{
174 Lisp_Object watch_object; 129 Lisp_Object watch_object;
175 GFile *gfile; 130 int fd;
176 GFileMonitor *monitor; 131 u_short fflags = 0;
177 GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; 132 struct kevent ev;
178 GError *gerror = NULL;
179 133
180 /* Check parameters. */ 134 /* Check parameters. */
181 CHECK_STRING (file); 135 CHECK_STRING (file);
@@ -183,80 +137,62 @@ will be reported only in case of the `moved' event. */)
183 if (NILP (Ffile_exists_p (file))) 137 if (NILP (Ffile_exists_p (file)))
184 report_file_error ("File does not exist", file); 138 report_file_error ("File does not exist", file);
185 139
140 /* TODO: Directories shall be supported as well. */
141 if (!NILP (Ffile_directory_p (file)))
142 report_file_error ("Directory watching is not supported (yet)", file);
143
186 CHECK_LIST (flags); 144 CHECK_LIST (flags);
187 145
188 if (!FUNCTIONP (callback)) 146 if (!FUNCTIONP (callback))
189 wrong_type_argument (Qinvalid_function, callback); 147 wrong_type_argument (Qinvalid_function, callback);
190 148
191 /* Create GFile name. */
192 // gfile = g_file_new_for_path (SSDATA (ENCODE_FILE (file)));
193
194 /* Assemble flags. */
195 // if (!NILP (Fmember (Qwatch_mounts, flags)))
196 // gflags |= G_FILE_MONITOR_WATCH_MOUNTS;
197 // if (!NILP (Fmember (Qsend_moved, flags)))
198 // gflags |= G_FILE_MONITOR_SEND_MOVED;
199
200 if (kqueuefd < 0) 149 if (kqueuefd < 0)
201 { 150 {
151 /* Create kqueue descriptor. */
202 kqueuefd = kqueue (); 152 kqueuefd = kqueue ();
203 if (kqueuefd < 0) 153 if (kqueuefd < 0)
204 report_file_notify_error ("File watching is not available", Qnil); 154 report_file_notify_error ("File watching is not available", Qnil);
205 watch_list = Qnil;
206 // add_read_fd (inotifyfd, &inotify_callback, NULL);
207 }
208
209
210}
211#if 0
212 155
213 mask = aspect_to_inotifymask (aspect); 156 /* Start monitoring for possible I/O. */
214 encoded_file_name = ENCODE_FILE (file_name); 157 add_read_fd (kqueuefd, kqueue_callback, NULL); //data);
215 watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask);
216 if (watchdesc == -1)
217 report_file_notify_error ("Could not add watch for file", file_name);
218 158
219 /* Enable watch. */ 159 watch_list = Qnil;
220 monitor = g_file_monitor (gfile, gflags, NULL, &gerror);
221 g_object_unref (gfile);
222 if (gerror)
223 {
224 char msg[1024];
225 strcpy (msg, gerror->message);
226 g_error_free (gerror);
227 xsignal1 (Qfile_notify_error, build_string (msg));
228 } 160 }
229 if (! monitor)
230 xsignal2 (Qfile_notify_error, build_string ("Cannot watch file"), file);
231 161
232 Lisp_Object watch_descriptor = make_pointer_integer (monitor); 162 /* Open file. */
163 file = ENCODE_FILE (file);
164 fd = emacs_open (SSDATA (file), O_NONBLOCK | O_BINARY | O_RDONLY, 0);
165 if (fd == -1)
166 report_file_error ("File cannot be opened", file);
233 167
234 /* Check the dicey assumption that make_pointer_integer is safe. */ 168 /* Assemble filter flags */
235 if (! INTEGERP (watch_descriptor)) 169 if (!NILP (Fmember (Qdelete, flags))) fflags |= NOTE_DELETE;
236 { 170 if (!NILP (Fmember (Qwrite, flags))) fflags |= NOTE_WRITE;
237 g_object_unref (monitor); 171 if (!NILP (Fmember (Qextend, flags))) fflags |= NOTE_EXTEND;
238 xsignal2 (Qfile_notify_error, build_string ("Unsupported file watcher"), 172 if (!NILP (Fmember (Qattrib, flags))) fflags |= NOTE_ATTRIB;
239 file); 173 if (!NILP (Fmember (Qlink, flags))) fflags |= NOTE_LINK;
240 } 174 if (!NILP (Fmember (Qrename, flags))) fflags |= NOTE_RENAME;
241 175
242 /* The default rate limit is 800 msec. We adapt this. */ 176 /* Register event. */
243 g_file_monitor_set_rate_limit (monitor, 100); 177 EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
178 fflags, 0, NULL);
244 179
245 /* Subscribe to the "changed" signal. */ 180 if (kevent (kqueuefd, &ev, 1, NULL, 0, NULL) < 0)
246 g_signal_connect (monitor, "changed", 181 report_file_error ("Cannot watch file", file);
247 (GCallback) dir_monitor_callback, NULL);
248 182
249 /* Store watch object in watch list. */ 183 /* Store watch object in watch list. */
184 Lisp_Object watch_descriptor = make_number (fd);
250 watch_object = list4 (watch_descriptor, file, flags, callback); 185 watch_object = list4 (watch_descriptor, file, flags, callback);
251 watch_list = Fcons (watch_object, watch_list); 186 watch_list = Fcons (watch_object, watch_list);
252 187
253 return watch_descriptor; 188 return watch_descriptor;
254} 189}
255 190
256DEFUN ("gfile-rm-watch", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0, 191#if 0
192DEFUN ("kqueue-rm-watch", Fkqueue_rm_watch, Skqueue_rm_watch, 1, 1, 0,
257 doc: /* Remove an existing WATCH-DESCRIPTOR. 193 doc: /* Remove an existing WATCH-DESCRIPTOR.
258 194
259WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */) 195WATCH-DESCRIPTOR should be an object returned by `kqueue-add-watch'. */)
260 (Lisp_Object watch_descriptor) 196 (Lisp_Object watch_descriptor)
261{ 197{
262 Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list); 198 Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list);
@@ -317,12 +253,6 @@ syms_of_kqueue (void)
317 // defsubr (&Skqueue_rm_watch); 253 // defsubr (&Skqueue_rm_watch);
318 // defsubr (&Skqueue_valid_p); 254 // defsubr (&Skqueue_valid_p);
319 255
320 /* Filter objects. */
321 DEFSYM (Qchange, "change");
322 DEFSYM (Qattribute_change, "attribute-change");
323 DEFSYM (Qwatch_mounts, "watch-mounts"); /* G_FILE_MONITOR_WATCH_MOUNTS */
324 DEFSYM (Qsend_moved, "send-moved"); /* G_FILE_MONITOR_SEND_MOVED */
325
326 /* Event types. */ 256 /* Event types. */
327 DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */ 257 DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */
328 DEFSYM (Qwrite, "write"); /* NOTE_WRITE */ 258 DEFSYM (Qwrite, "write"); /* NOTE_WRITE */