mirror of
https://github.com/neovim/neovim.git
synced 2024-12-29 14:41:06 -07:00
Reimplement the event queue in event.c using klist.h
- Add a new macro to klist.h: kl_empty() The whole point of abstract data structures is to avoid reimplementing common actions. The emptiness test seems to be such an action. - Add a new function attribute to func_attr.h: FUNC_ATTR_UNUSED Some of the many functions created by the macros in klist.h may end up not being used. Unused functions cause compilation errors as we compile with -Werror. To mark those functions as possibly unused we can use the FUNC_ATTR_UNUSED now. - Pass `Event` by value `Event` is such a small struct that I don't think we should allocate heap space and pass it by reference. Let's use the stack and memory cache in our favor passing it by value.
This commit is contained in:
parent
fac85c1724
commit
967fb1aca6
@ -34,6 +34,7 @@
|
||||
#define FUNC_ATTR_CONST __attribute__((const))
|
||||
#define FUNC_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#define FUNC_ATTR_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#define FUNC_ATTR_UNUSED __attribute__((unused))
|
||||
|
||||
#ifdef __clang__
|
||||
// clang only
|
||||
@ -90,6 +91,10 @@
|
||||
#define FUNC_ATTR_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_UNUSED
|
||||
#define FUNC_ATTR_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef FUNC_ATTR_NONNULL_ALL
|
||||
#define FUNC_ATTR_NONNULL_ALL
|
||||
#endif
|
||||
|
@ -26,8 +26,10 @@
|
||||
#ifndef _AC_KLIST_H
|
||||
#define _AC_KLIST_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "func_attr.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \
|
||||
@ -84,6 +86,8 @@
|
||||
kl->head->next = 0; \
|
||||
return kl; \
|
||||
} \
|
||||
static inline void kl_destroy_##name(kl_##name##_t *kl) \
|
||||
FUNC_ATTR_UNUSED; \
|
||||
static inline void kl_destroy_##name(kl_##name##_t *kl) { \
|
||||
kl1_##name *p; \
|
||||
for (p = kl->head; p != kl->tail; p = p->next) \
|
||||
@ -119,5 +123,6 @@
|
||||
#define kl_destroy(name, kl) kl_destroy_##name(kl)
|
||||
#define kl_pushp(name, kl) kl_pushp_##name(kl)
|
||||
#define kl_shift(name, kl, d) kl_shift_##name(kl, d)
|
||||
#define kl_empty(kl) ((kl)->size == 0)
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include "lib/klist.h"
|
||||
#include "os/event.h"
|
||||
#include "os/input.h"
|
||||
#include "os/signal.h"
|
||||
@ -11,22 +12,22 @@
|
||||
#include "memory.h"
|
||||
#include "misc2.h"
|
||||
|
||||
typedef struct EventNode {
|
||||
Event *event;
|
||||
struct EventNode *next;
|
||||
} EventNode;
|
||||
// event.data will be cleaned up after the event is processed
|
||||
#define _destroy_event(x) // do nothing
|
||||
KLIST_INIT(Event, Event, _destroy_event)
|
||||
|
||||
static EventNode *head, *tail;
|
||||
static klist_t(Event) *event_queue;
|
||||
static uv_timer_t timer;
|
||||
static uv_prepare_t timer_prepare;
|
||||
static bool poll_uv_loop(int ms);
|
||||
static void process_all_events(void);
|
||||
static bool has_pending_events(void);
|
||||
static void timer_cb(uv_timer_t *handle, int);
|
||||
static void timer_prepare_cb(uv_prepare_t *, int);
|
||||
|
||||
void event_init()
|
||||
{
|
||||
// Initialize the event queue
|
||||
event_queue = kl_init(Event);
|
||||
// Initialize input events
|
||||
input_init();
|
||||
// Timer to wake the event loop if a timeout argument is passed to
|
||||
@ -72,50 +73,27 @@ bool event_poll(int32_t ms)
|
||||
}
|
||||
|
||||
// Push an event to the queue
|
||||
void event_push(Event *event)
|
||||
void event_push(Event event)
|
||||
{
|
||||
EventNode *node = (EventNode *)xmalloc(sizeof(EventNode));
|
||||
node->event = event;
|
||||
node->next = NULL;
|
||||
|
||||
if (head == NULL) {
|
||||
head = node;
|
||||
} else {
|
||||
tail->next = node;
|
||||
}
|
||||
|
||||
tail = node;
|
||||
*kl_pushp(Event, event_queue) = event;
|
||||
}
|
||||
|
||||
// Runs the appropriate action for each queued event
|
||||
static void process_all_events()
|
||||
{
|
||||
EventNode *next;
|
||||
Event *event;
|
||||
Event event;
|
||||
|
||||
while (has_pending_events()) {
|
||||
next = head->next;
|
||||
event = head->event;
|
||||
free(head);
|
||||
head = next;
|
||||
|
||||
switch (event->type) {
|
||||
while (kl_shift(Event, event_queue, &event) == 0) {
|
||||
switch (event.type) {
|
||||
case kEventSignal:
|
||||
signal_handle(event);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if there are queued events
|
||||
bool has_pending_events()
|
||||
{
|
||||
return head != NULL;
|
||||
}
|
||||
|
||||
// Wait for some event
|
||||
static bool poll_uv_loop(int32_t ms)
|
||||
{
|
||||
@ -150,7 +128,7 @@ static bool poll_uv_loop(int32_t ms)
|
||||
} while (
|
||||
// Continue running if ...
|
||||
!input_ready() && // we have no input
|
||||
!has_pending_events() && // no events are waiting to be processed
|
||||
kl_empty(event_queue) && // no events are waiting to be processed
|
||||
run_mode != UV_RUN_NOWAIT && // ms != 0
|
||||
!timed_out // we didn't get a timeout
|
||||
);
|
||||
@ -162,7 +140,7 @@ static bool poll_uv_loop(int32_t ms)
|
||||
uv_timer_stop(&timer);
|
||||
}
|
||||
|
||||
return input_ready() || has_pending_events();
|
||||
return input_ready() || !kl_empty(event_queue);
|
||||
}
|
||||
|
||||
// Set a flag in the `event_poll` loop for signaling of a timeout
|
||||
|
@ -15,7 +15,7 @@ typedef struct {
|
||||
|
||||
void event_init(void);
|
||||
bool event_poll(int32_t ms);
|
||||
void event_push(Event *event);
|
||||
void event_push(Event event);
|
||||
|
||||
#endif // NEOVIM_OS_EVENT_H
|
||||
|
||||
|
@ -67,12 +67,11 @@ void signal_accept_deadly()
|
||||
rejecting_deadly = false;
|
||||
}
|
||||
|
||||
void signal_handle(Event *event)
|
||||
void signal_handle(Event event)
|
||||
{
|
||||
int signum = *(int *)event->data;
|
||||
int signum = *(int *)event.data;
|
||||
|
||||
free(event->data);
|
||||
free(event);
|
||||
free(event.data);
|
||||
|
||||
switch (signum) {
|
||||
case SIGINT:
|
||||
@ -148,8 +147,6 @@ static void deadly_signal(int signum)
|
||||
|
||||
static void signal_cb(uv_signal_t *handle, int signum)
|
||||
{
|
||||
Event *event;
|
||||
|
||||
if (rejecting_deadly) {
|
||||
if (signum == SIGINT) {
|
||||
got_int = true;
|
||||
@ -158,9 +155,10 @@ static void signal_cb(uv_signal_t *handle, int signum)
|
||||
return;
|
||||
}
|
||||
|
||||
event = (Event *)xmalloc(sizeof(Event));
|
||||
event->type = kEventSignal;
|
||||
event->data = xmalloc(sizeof(int));
|
||||
*(int *)event->data = signum;
|
||||
Event event = {
|
||||
.type = kEventSignal,
|
||||
.data = xmalloc(sizeof(int))
|
||||
};
|
||||
*(int *)event.data = signum;
|
||||
event_push(event);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ void signal_init(void);
|
||||
void signal_stop(void);
|
||||
void signal_accept_deadly(void);
|
||||
void signal_reject_deadly(void);
|
||||
void signal_handle(Event *event);
|
||||
void signal_handle(Event event);
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user