diff options
| author | Fabrice Popineau | 2016-03-19 14:44:53 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-03-19 14:44:53 +0200 |
| commit | 326fff41fa9f674d80be00b5c97c44f8043bbace (patch) | |
| tree | 15f5e2fb315130ce923970d16a96c8e951914857 /src/w32term.c | |
| parent | 2fbdb1bb4c878f8ae17bd69d1b4ff51c47497e41 (diff) | |
| download | emacs-326fff41fa9f674d80be00b5c97c44f8043bbace.tar.gz emacs-326fff41fa9f674d80be00b5c97c44f8043bbace.zip | |
Improve w32notify notifications
* src/w32notify.c (DIRWATCH_BUFFER_SIZE): New macro.
(struct notification): 'terminate' is now a HANDLE.
(send_notifications): Argument is now a pointer to a
notification. Don't loop waiting for the notification to be
acknowledged by the main thread; instead, just add the
notification to the linked list of notifications waiting to be
acknowledged.
(watch_end): Don't close the directory handle.
(watch_completion): Allocate a new notification structure to be
added to the notifications set. Call ReadDirectoryChangesW
immediately after adding the new notification, and before sending
a message to the main thread about them.
(watch_worker): Don't loop calling ReadDirectoryChangesW; instead,
call it just once -- it will be called again in watch_completion.
Loop waiting for the main thread's indication to terminate.
(start_watching): Create the event to be used to indicate to the
worker thread that its should terminate.
(remove_watch): Indicate to the worker thread that it should
terminate.
* src/w32term.c (queue_notifications): Loop over all the
notifications in the linked list, processing all of them in one
go.
* src/w32inevt.c (handle_file_notifications): Loop over all the
notifications in the linked list.
* src/w32xfns.c (init_crit): Initialize the linked list of file
notifications.
(delete_crit): Free the linked list of file notifications,
including any unprocessed notifications left in it.
* src/w32term.h (struct notifications_se): New struct.
* test/lisp/filenotify-tests.el (file-notify-test02-events)
(file-notify-test05-dir-validity): Add read-event calls to
facilitate event recognition by the main thread in batch mode.
Diffstat (limited to 'src/w32term.c')
| -rw-r--r-- | src/w32term.c | 116 |
1 files changed, 66 insertions, 50 deletions
diff --git a/src/w32term.c b/src/w32term.c index 62ad4eb086b..8955ce26b4b 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -3211,71 +3211,85 @@ static void | |||
| 3211 | queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f, | 3211 | queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f, |
| 3212 | int *evcount) | 3212 | int *evcount) |
| 3213 | { | 3213 | { |
| 3214 | BYTE *p = file_notifications; | 3214 | struct notifications_set *ns = NULL; |
| 3215 | FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p; | ||
| 3216 | const DWORD min_size | ||
| 3217 | = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t); | ||
| 3218 | Lisp_Object frame; | 3215 | Lisp_Object frame; |
| 3216 | int done = 0; | ||
| 3219 | 3217 | ||
| 3220 | /* We cannot process notification before Emacs is fully initialized, | 3218 | /* We cannot process notification before Emacs is fully initialized, |
| 3221 | since we need the UTF-16LE coding-system to be set up. */ | 3219 | since we need the UTF-16LE coding-system to be set up. */ |
| 3222 | if (!initialized) | 3220 | if (!initialized) |
| 3223 | { | 3221 | return; |
| 3224 | notification_buffer_in_use = 0; | ||
| 3225 | return; | ||
| 3226 | } | ||
| 3227 | 3222 | ||
| 3228 | XSETFRAME (frame, f); | 3223 | XSETFRAME (frame, f); |
| 3229 | 3224 | ||
| 3230 | enter_crit (); | 3225 | while (!done) |
| 3231 | if (notification_buffer_in_use) | ||
| 3232 | { | 3226 | { |
| 3233 | DWORD info_size = notifications_size; | 3227 | ns = NULL; |
| 3234 | Lisp_Object cs = Qutf_16le; | 3228 | |
| 3235 | Lisp_Object obj = w32_get_watch_object (notifications_desc); | 3229 | /* Find out if there is a record available in the linked list of |
| 3236 | 3230 | notifications sets. If so, unlink the set from the linked | |
| 3237 | /* notifications_size could be zero when the buffer of | 3231 | list. Use critical section. */ |
| 3238 | notifications overflowed on the OS level, or when the | 3232 | enter_crit (); |
| 3239 | directory being watched was itself deleted. Do nothing in | 3233 | if (notifications_set_head->next != notifications_set_head) |
| 3240 | that case. */ | ||
| 3241 | if (info_size | ||
| 3242 | && !NILP (obj) && CONSP (obj)) | ||
| 3243 | { | 3234 | { |
| 3244 | Lisp_Object callback = XCDR (obj); | 3235 | ns = notifications_set_head->next; |
| 3236 | ns->prev->next = ns->next; | ||
| 3237 | ns->next->prev = ns->prev; | ||
| 3238 | } | ||
| 3239 | else | ||
| 3240 | done = 1; | ||
| 3241 | leave_crit(); | ||
| 3245 | 3242 | ||
| 3246 | while (info_size >= min_size) | 3243 | if (ns) |
| 3244 | { | ||
| 3245 | BYTE *p = ns->notifications; | ||
| 3246 | FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p; | ||
| 3247 | const DWORD min_size | ||
| 3248 | = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t); | ||
| 3249 | DWORD info_size = ns->size; | ||
| 3250 | Lisp_Object cs = Qutf_16le; | ||
| 3251 | Lisp_Object obj = w32_get_watch_object (ns->desc); | ||
| 3252 | |||
| 3253 | /* notifications size could be zero when the buffer of | ||
| 3254 | notifications overflowed on the OS level, or when the | ||
| 3255 | directory being watched was itself deleted. Do nothing in | ||
| 3256 | that case. */ | ||
| 3257 | if (info_size | ||
| 3258 | && !NILP (obj) && CONSP (obj)) | ||
| 3247 | { | 3259 | { |
| 3248 | Lisp_Object utf_16_fn | 3260 | Lisp_Object callback = XCDR (obj); |
| 3249 | = make_unibyte_string ((char *)fni->FileName, | 3261 | |
| 3250 | fni->FileNameLength); | 3262 | while (info_size >= min_size) |
| 3251 | /* Note: mule-conf is preloaded, so utf-16le must | 3263 | { |
| 3252 | already be defined at this point. */ | 3264 | Lisp_Object utf_16_fn |
| 3253 | Lisp_Object fname | 3265 | = make_unibyte_string ((char *)fni->FileName, |
| 3254 | = code_convert_string_norecord (utf_16_fn, cs, 0); | 3266 | fni->FileNameLength); |
| 3255 | Lisp_Object action = lispy_file_action (fni->Action); | 3267 | /* Note: mule-conf is preloaded, so utf-16le must |
| 3256 | 3268 | already be defined at this point. */ | |
| 3257 | event->kind = FILE_NOTIFY_EVENT; | 3269 | Lisp_Object fname |
| 3258 | event->timestamp = msg->msg.time; | 3270 | = code_convert_string_norecord (utf_16_fn, cs, 0); |
| 3259 | event->modifiers = 0; | 3271 | Lisp_Object action = lispy_file_action (fni->Action); |
| 3260 | event->frame_or_window = callback; | 3272 | |
| 3261 | event->arg = list3 (make_pointer_integer (notifications_desc), | 3273 | event->kind = FILE_NOTIFY_EVENT; |
| 3262 | action, fname); | 3274 | event->timestamp = msg->msg.time; |
| 3263 | kbd_buffer_store_event (event); | 3275 | event->modifiers = 0; |
| 3264 | (*evcount)++; | 3276 | event->frame_or_window = callback; |
| 3265 | 3277 | event->arg = list3 (make_pointer_integer (ns->desc), | |
| 3266 | if (!fni->NextEntryOffset) | 3278 | action, fname); |
| 3267 | break; | 3279 | kbd_buffer_store_event (event); |
| 3268 | p += fni->NextEntryOffset; | 3280 | (*evcount)++; |
| 3269 | fni = (PFILE_NOTIFY_INFORMATION)p; | 3281 | if (!fni->NextEntryOffset) |
| 3270 | info_size -= fni->NextEntryOffset; | 3282 | break; |
| 3283 | p += fni->NextEntryOffset; | ||
| 3284 | fni = (PFILE_NOTIFY_INFORMATION)p; | ||
| 3285 | info_size -= fni->NextEntryOffset; | ||
| 3286 | } | ||
| 3271 | } | 3287 | } |
| 3288 | /* Free this notifications set. */ | ||
| 3289 | xfree (ns->notifications); | ||
| 3290 | xfree (ns); | ||
| 3272 | } | 3291 | } |
| 3273 | notification_buffer_in_use = 0; | ||
| 3274 | } | 3292 | } |
| 3275 | else | ||
| 3276 | DebPrint (("We were promised notifications, but in-use flag is zero!\n")); | ||
| 3277 | leave_crit (); | ||
| 3278 | |||
| 3279 | /* We've stuffed all the events ourselves, so w32_read_socket shouldn't. */ | 3293 | /* We've stuffed all the events ourselves, so w32_read_socket shouldn't. */ |
| 3280 | event->kind = NO_EVENT; | 3294 | event->kind = NO_EVENT; |
| 3281 | } | 3295 | } |
| @@ -6949,6 +6963,8 @@ w32_init_main_thread (void) | |||
| 6949 | DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), | 6963 | DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), |
| 6950 | GetCurrentProcess (), &hMainThread, 0, TRUE, | 6964 | GetCurrentProcess (), &hMainThread, 0, TRUE, |
| 6951 | DUPLICATE_SAME_ACCESS); | 6965 | DUPLICATE_SAME_ACCESS); |
| 6966 | |||
| 6967 | |||
| 6952 | } | 6968 | } |
| 6953 | 6969 | ||
| 6954 | DWORD WINAPI w32_msg_worker (void * arg); | 6970 | DWORD WINAPI w32_msg_worker (void * arg); |