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 | |
12 | typedef void * WatcherPtr; |
13 | |
14 | #define _noop(x) |
15 | KLIST_INIT(WatcherPtr, WatcherPtr, _noop) |
16 | |
17 | typedef 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 | |