Updated libgit to version 2.46.2 based on Git for Windows sources
[TortoiseGit.git] / src / TortoisePlink / Windows / cliloop.c
blob505a59cd25d34f879033ea3538840f0eeb3de455
1 #include "putty.h"
3 void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx)
5 SOCKET *sklist = NULL;
6 size_t skcount = 0, sksize = 0;
7 unsigned long now, next, then;
8 now = GETTICKCOUNT();
10 while (true) {
11 DWORD n;
12 DWORD ticks;
14 const HANDLE *extra_handles = NULL;
15 size_t n_extra_handles = 0;
16 if (!pre(ctx, &extra_handles, &n_extra_handles))
17 break;
19 if (toplevel_callback_pending()) {
20 ticks = 0;
21 next = now;
22 } else if (run_timers(now, &next)) {
23 then = now;
24 now = GETTICKCOUNT();
25 if (now - then > next - then)
26 ticks = 0;
27 else
28 ticks = next - now;
29 } else {
30 ticks = INFINITE;
31 /* no need to initialise next here because we can never
32 * get WAIT_TIMEOUT */
35 HandleWaitList *hwl = get_handle_wait_list();
36 size_t winselcli_index = -(size_t)1;
37 size_t extra_base = hwl->nhandles;
38 if (winselcli_event != INVALID_HANDLE_VALUE) {
39 assert(extra_base < MAXIMUM_WAIT_OBJECTS);
40 winselcli_index = extra_base++;
41 hwl->handles[winselcli_index] = winselcli_event;
43 size_t total_handles = extra_base + n_extra_handles;
44 assert(total_handles < MAXIMUM_WAIT_OBJECTS);
45 for (size_t i = 0; i < n_extra_handles; i++)
46 hwl->handles[extra_base + i] = extra_handles[i];
48 n = WaitForMultipleObjects(total_handles, hwl->handles, false, ticks);
50 size_t extra_handle_index = n_extra_handles;
52 if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)hwl->nhandles) {
53 handle_wait_activate(hwl, n - WAIT_OBJECT_0);
54 } else if (winselcli_event != INVALID_HANDLE_VALUE &&
55 n == WAIT_OBJECT_0 + winselcli_index) {
56 WSANETWORKEVENTS things;
57 SOCKET socket;
58 int i, socketstate;
61 * We must not call select_result() for any socket
62 * until we have finished enumerating within the tree.
63 * This is because select_result() may close the socket
64 * and modify the tree.
66 /* Count the active sockets. */
67 i = 0;
68 for (socket = first_socket(&socketstate);
69 socket != INVALID_SOCKET;
70 socket = next_socket(&socketstate)) i++;
72 /* Expand the buffer if necessary. */
73 sgrowarray(sklist, sksize, i);
75 /* Retrieve the sockets into sklist. */
76 skcount = 0;
77 for (socket = first_socket(&socketstate);
78 socket != INVALID_SOCKET;
79 socket = next_socket(&socketstate)) {
80 sklist[skcount++] = socket;
83 /* Now we're done enumerating; go through the list. */
84 for (i = 0; i < skcount; i++) {
85 WPARAM wp;
86 socket = sklist[i];
87 wp = (WPARAM) socket;
88 if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) {
89 static const struct { int bit, mask; } eventtypes[] = {
90 {FD_CONNECT_BIT, FD_CONNECT},
91 {FD_READ_BIT, FD_READ},
92 {FD_CLOSE_BIT, FD_CLOSE},
93 {FD_OOB_BIT, FD_OOB},
94 {FD_WRITE_BIT, FD_WRITE},
95 {FD_ACCEPT_BIT, FD_ACCEPT},
97 int e;
99 noise_ultralight(NOISE_SOURCE_IOID, socket);
101 for (e = 0; e < lenof(eventtypes); e++)
102 if (things.lNetworkEvents & eventtypes[e].mask) {
103 LPARAM lp;
104 int err = things.iErrorCode[eventtypes[e].bit];
105 lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err);
106 select_result(wp, lp);
110 } else if (n >= WAIT_OBJECT_0 + extra_base &&
111 n < WAIT_OBJECT_0 + extra_base + n_extra_handles) {
112 extra_handle_index = n - (WAIT_OBJECT_0 + extra_base);
115 run_toplevel_callbacks();
117 if (n == WAIT_TIMEOUT) {
118 now = next;
119 } else {
120 now = GETTICKCOUNT();
123 handle_wait_list_free(hwl);
125 if (!post(ctx, extra_handle_index))
126 break;
129 sfree(sklist);
132 bool cliloop_null_pre(void *vctx, const HANDLE **eh, size_t *neh)
133 { return true; }
134 bool cliloop_null_post(void *vctx, size_t ehi) { return true; }