1#ifndef NVIM_EVENT_LOOP_H
2#define NVIM_EVENT_LOOP_H
3
4#include <stdint.h>
5
6#include <uv.h>
7
8#include "nvim/lib/klist.h"
9#include "nvim/os/time.h"
10#include "nvim/event/multiqueue.h"
11
12typedef void * WatcherPtr;
13
14#define _noop(x)
15KLIST_INIT(WatcherPtr, WatcherPtr, _noop)
16
17typedef struct loop {
18 uv_loop_t uv;
19 MultiQueue *events;
20 MultiQueue *thread_events;
21 // Immediate events:
22 // "Processed after exiting uv_run() (to avoid recursion), but before
23 // returning from loop_poll_events()." 502aee690c98
24 // Practical consequence (for main_loop): these events are processed by
25 // state_enter()..os_inchar()
26 // whereas "regular" events (main_loop.events) are processed by
27 // state_enter()..VimState.execute()
28 // But state_enter()..os_inchar() can be "too early" if you want the event
29 // to trigger UI updates and other user-activity-related side-effects.
30 MultiQueue *fast_events;
31
32 // used by process/job-control subsystem
33 klist_t(WatcherPtr) *children;
34 uv_signal_t children_watcher;
35 uv_timer_t children_kill_timer;
36
37 // generic timer, used by loop_poll_events()
38 uv_timer_t poll_timer;
39
40 uv_async_t async;
41 uv_mutex_t mutex;
42 int recursive;
43} Loop;
44
45#define CREATE_EVENT(multiqueue, handler, argc, ...) \
46 do { \
47 if (multiqueue) { \
48 multiqueue_put((multiqueue), (handler), argc, __VA_ARGS__); \
49 } else { \
50 void *argv[argc] = { __VA_ARGS__ }; \
51 (handler)(argv); \
52 } \
53 } while (0)
54
55// -V:LOOP_PROCESS_EVENTS_UNTIL:547
56
57// Poll for events until a condition or timeout
58#define LOOP_PROCESS_EVENTS_UNTIL(loop, multiqueue, timeout, condition) \
59 do { \
60 int remaining = timeout; \
61 uint64_t before = (remaining > 0) ? os_hrtime() : 0; \
62 while (!(condition)) { \
63 LOOP_PROCESS_EVENTS(loop, multiqueue, remaining); \
64 if (remaining == 0) { \
65 break; \
66 } else if (remaining > 0) { \
67 uint64_t now = os_hrtime(); \
68 remaining -= (int) ((now - before) / 1000000); \
69 before = now; \
70 if (remaining <= 0) { \
71 break; \
72 } \
73 } \
74 } \
75 } while (0)
76
77#define LOOP_PROCESS_EVENTS(loop, multiqueue, timeout) \
78 do { \
79 if (multiqueue && !multiqueue_empty(multiqueue)) { \
80 multiqueue_process_events(multiqueue); \
81 } else { \
82 loop_poll_events(loop, timeout); \
83 } \
84 } while (0)
85
86
87#ifdef INCLUDE_GENERATED_DECLARATIONS
88# include "event/loop.h.generated.h"
89#endif
90
91#endif // NVIM_EVENT_LOOP_H
92