From: Jan D Date: Wed, 7 Jul 2010 17:39:49 +0000 (+0200) Subject: If kbd_buffer is becoming full, stop reading until it drains (Bug#6571). X-Git-Tag: emacs-pretest-24.0.90~104^2~275^2~438^2~51^2~81^2~8 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=cb768704a459ab54632daf5bb1a10127a6a5c9f7;p=emacs.git If kbd_buffer is becoming full, stop reading until it drains (Bug#6571). * keyboard.c (input_available_signal): Declare. (kbd_buffer_nr_stored): New function. (kbd_buffer_store_event_hold): If kbd_buffer_nr_stored returns more than KBD_BUFFER_SIZE/2, stop reding input (Bug#6571). (kbd_buffer_get_event): If input is suspended and kbd_buffer_nr_stored returns less than KBD_BUFFER_SIZE/4, resume reding input (Bug#6571). (tty_read_avail_input): If input is on hold, return. Don't read more that free slots in kbd_buffer (Bug#6571). * process.h (hold_keyboard_input, unhold_keyboard_input) (kbd_on_hold_p): Declare. * process.c (kbd_is_on_hold): New variable. (hold_keyboard_input, unhold_keyboard_input, kbd_on_hold_p): New functions. (wait_reading_process_output): If kbd_on_hold_p returns non-zero, select on empty input mask. (init_process): Initialize kbd_is_on_hold to 0. --- diff --git a/src/ChangeLog b/src/ChangeLog index 63b0dd0a53d..912a5a8d2f2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,24 @@ +2010-07-07 Jan Djärv + + * process.c (kbd_is_on_hold): New variable. + (hold_keyboard_input, unhold_keyboard_input, kbd_on_hold_p): New + functions. + (wait_reading_process_output): If kbd_on_hold_p returns non-zero, + select on empty input mask. + (init_process): Initialize kbd_is_on_hold to 0. + + * process.h (hold_keyboard_input, unhold_keyboard_input) + (kbd_on_hold_p): Declare. + + * keyboard.c (input_available_signal): Declare. + (kbd_buffer_nr_stored): New function. + (kbd_buffer_store_event_hold): If kbd_buffer_nr_stored returns + more than KBD_BUFFER_SIZE/2, stop reding input (Bug#6571). + (kbd_buffer_get_event): If input is suspended and kbd_buffer_nr_stored + returns less than KBD_BUFFER_SIZE/4, resume reding input (Bug#6571). + (tty_read_avail_input): If input is on hold, return. + Don't read more that free slots in kbd_buffer (Bug#6571). + 2010-07-07 Eli Zaretskii * msdos.h: diff --git a/src/keyboard.c b/src/keyboard.c index 2cf7a7b24a6..c7d3ee413cd 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -635,6 +635,7 @@ static Lisp_Object apply_modifiers (int, Lisp_Object); static void clear_event (struct input_event *); static Lisp_Object restore_kboard_configuration (Lisp_Object); static SIGTYPE interrupt_signal (int signalnum); +static SIGTYPE input_available_signal (int signo); static void handle_interrupt (void); static void timer_start_idle (void); static void timer_stop_idle (void); @@ -3590,6 +3591,18 @@ event_to_kboard (struct input_event *event) return FRAME_KBOARD (XFRAME (frame)); } +/* Return the number of slots occupied in kbd_buffer. */ + +static int +kbd_buffer_nr_stored () +{ + return kbd_fetch_ptr == kbd_store_ptr + ? 0 + : (kbd_fetch_ptr < kbd_store_ptr + ? kbd_store_ptr - kbd_fetch_ptr + : ((kbd_buffer + KBD_BUFFER_SIZE) - kbd_fetch_ptr + + (kbd_store_ptr - kbd_buffer))); +} Lisp_Object Vthrow_on_input; @@ -3711,6 +3724,17 @@ kbd_buffer_store_event_hold (register struct input_event *event, { *kbd_store_ptr = *event; ++kbd_store_ptr; + if (kbd_buffer_nr_stored () > KBD_BUFFER_SIZE/2 && ! kbd_on_hold_p ()) + { + /* Don't read keyboard input until we have processed kbd_buffer. + This happens when pasting text longer than KBD_BUFFER_SIZE/2. */ + hold_keyboard_input (); +#ifdef SIGIO + if (!noninteractive) + signal (SIGIO, SIG_IGN); +#endif + stop_polling (); + } } /* If we're inside while-no-input, and this event qualifies @@ -3866,10 +3890,24 @@ clear_event (struct input_event *event) We always read and discard one event. */ static Lisp_Object -kbd_buffer_get_event (KBOARD **kbp, int *used_mouse_menu, struct timeval *end_time) +kbd_buffer_get_event (KBOARD **kbp, + int *used_mouse_menu, + struct timeval *end_time) { register int c; Lisp_Object obj; + + if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE/4) + { + /* Start reading input again, we have processed enough so we can + accept new events again. */ + unhold_keyboard_input (); +#ifdef SIGIO + if (!noninteractive) + signal (SIGIO, input_available_signal); +#endif /* SIGIO */ + start_polling (); + } if (noninteractive /* In case we are running as a daemon, only do this before @@ -7039,6 +7077,10 @@ tty_read_avail_input (struct terminal *terminal, int n_to_read, i; struct tty_display_info *tty = terminal->display_info.tty; int nread = 0; + int buffer_free = KBD_BUFFER_SIZE - kbd_buffer_nr_stored () - 1; + + if (kbd_on_hold_p () || buffer_free <= 0) + return 0; if (!terminal->name) /* Don't read from a dead terminal. */ return 0; @@ -7120,6 +7162,10 @@ tty_read_avail_input (struct terminal *terminal, #endif #endif + /* Don't read more than we can store. */ + if (n_to_read > buffer_free) + n_to_read = buffer_free; + /* Now read; for one reason or another, this will not block. NREAD is set to the number of chars read. */ do diff --git a/src/process.c b/src/process.c index 0807a0e17cb..c7460d81255 100644 --- a/src/process.c +++ b/src/process.c @@ -306,6 +306,10 @@ extern int timers_run; static SELECT_TYPE input_wait_mask; +/* Non-zero if keyboard input is on hold, zero otherwise. */ + +static int kbd_is_on_hold; + /* Mask that excludes keyboard input descriptor(s). */ static SELECT_TYPE non_keyboard_wait_mask; @@ -4731,7 +4735,10 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, SELECT_TYPE Ctemp; #endif - Atemp = input_wait_mask; + if (kbd_on_hold_p ()) + FD_ZERO (&Atemp); + else + Atemp = input_wait_mask; IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask); EMACS_SET_SECS_USECS (timeout, 0, 0); @@ -7010,6 +7017,30 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p, +/* Stop reading input from keyboard sources. */ + +void +hold_keyboard_input (void) +{ + kbd_is_on_hold = 1; +} + +/* Resume reading input from keyboard sources. */ + +void +unhold_keyboard_input (void) +{ + kbd_is_on_hold = 0; +} + +/* Return non-zero if keyboard input is on hold, zero otherwise. */ + +int +kbd_on_hold_p (void) +{ + return kbd_is_on_hold; +} + /* Add DESC to the set of keyboard input descriptors. */ void @@ -7901,6 +7932,7 @@ integer or floating point values. void init_process () { + kbd_is_on_hold = 0; } void diff --git a/src/process.h b/src/process.h index a8cd0a02da6..12b91d697b9 100644 --- a/src/process.h +++ b/src/process.h @@ -170,5 +170,9 @@ extern Lisp_Object Qtime, Qctime; extern Lisp_Object list_system_processes (void); extern Lisp_Object system_process_attributes (Lisp_Object); +extern void hold_keyboard_input (void); +extern void unhold_keyboard_input (void); +extern int kbd_on_hold_p (void); + /* arch-tag: dffedfc4-d7bc-4b58-a26f-c16155449c72 (do not change this comment) */