input: allocate a small keystroke buffer, and never free it

Instead of allocating and freeing a tiny fragment of memory for every
keystroke, reserve a small piece in the beginning and then retain it,
because it will be needed again and again and again.  Increase the size
when needed (for a large paste, probably), but don't bother to shrink
it afterward.

This addresses the first part of https://savannah.gnu.org/bugs/?63086.
This commit is contained in:
Benno Schulenberg 2022-09-25 09:22:29 +02:00
parent 0d1438a731
commit 3922b531a8
2 changed files with 24 additions and 9 deletions

View File

@ -581,6 +581,7 @@ linestruct *line_from_number(ssize_t number);
/* Most functions in winio.c. */
void record_macro(void);
void run_macro(void);
void reserve_space_for(size_t newsize);
size_t waiting_keycodes(void);
#ifdef ENABLE_NANORC
void implant(const char *string);

View File

@ -46,6 +46,8 @@ static int *key_buffer = NULL;
/* A buffer for the keystrokes that haven't been handled yet. */
static int *nextcodes = NULL;
/* A pointer pointing at the next keycode in the keystroke buffer. */
static size_t capacity = 32;
/* The size of the keystroke buffer; gets doubled whenever needed. */
static size_t waiting_codes = 0;
/* The number of key codes waiting in the keystroke buffer. */
#ifdef ENABLE_NANORC
@ -126,7 +128,8 @@ void run_macro(void)
return;
}
key_buffer = nrealloc(key_buffer, macro_length * sizeof(int));
if (macro_length > capacity)
reserve_space_for(macro_length);
for (size_t i = 0; i < macro_length; i++)
key_buffer[i] = macro_buffer[i];
@ -137,6 +140,14 @@ void run_macro(void)
}
#endif /* !NANO_TINY */
/* Allocate the requested space for the keystroke buffer. */
void reserve_space_for(size_t newsize)
{
key_buffer = nrealloc(key_buffer, newsize * sizeof(int));
nextcodes = key_buffer;
capacity = newsize;
}
/* Control character compatibility:
*
* - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220.
@ -246,8 +257,10 @@ void read_keys_from(WINDOW *frame)
curs_set(0);
/* Initiate the keystroke buffer, and save the keycode in it. */
key_buffer = nrealloc(key_buffer, sizeof(int));
/* When there is no keystroke buffer yet, allocate one. */
if (!key_buffer)
reserve_space_for(capacity);
key_buffer[0] = input;
nextcodes = key_buffer;
@ -284,10 +297,11 @@ void read_keys_from(WINDOW *frame)
if (input == ERR)
break;
/* Extend the keystroke buffer, and save the keycode at its end. */
key_buffer = nrealloc(key_buffer, ++waiting_codes * sizeof(int));
key_buffer[waiting_codes - 1] = input;
nextcodes = key_buffer;
/* When the keystroke buffer is full, extend it. */
if (waiting_codes == capacity)
reserve_space_for(2 * capacity);
key_buffer[waiting_codes++] = input;
}
/* Restore blocking-input mode. */
@ -316,9 +330,9 @@ void put_back(int keycode)
/* If there is no room at the head of the keystroke buffer, make room. */
if (nextcodes == key_buffer) {
key_buffer = nrealloc(key_buffer, (waiting_codes + 1) * sizeof(int));
if (waiting_codes == capacity)
reserve_space_for(2 * capacity);
memmove(key_buffer + 1, key_buffer, waiting_codes * sizeof(int));
nextcodes = key_buffer;
} else
nextcodes--;