1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31 #include "handle-inl.h"
35 /* The only event loop we support right now */
36 static uv_loop_t uv_default_loop_;
38 /* uv_once intialization guards */
39 static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
40 static uv_once_t uv_default_loop_init_guard_ = UV_ONCE_INIT;
43 static void uv_init(void) {
44 /* Tell Windows that we will handle critical errors. */
45 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
46 SEM_NOOPENFILEERRORBOX);
48 /* Fetch winapi function pointers. This must be done first because other */
49 /* intialization code might need these function pointers to be loaded. */
52 /* Initialize winsock */
58 /* Initialize console */
61 /* Initialize utilities */
66 static void uv_loop_init(uv_loop_t* loop) {
67 /* Create an I/O completion port */
68 loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
69 if (loop->iocp == NULL) {
70 uv_fatal_error(GetLastError(), "CreateIoCompletionPort");
75 ngx_queue_init(&loop->handle_queue);
76 ngx_queue_init(&loop->active_reqs);
77 loop->active_handles = 0;
79 loop->pending_reqs_tail = NULL;
81 loop->endgame_handles = NULL;
83 RB_INIT(&loop->timers);
85 loop->check_handles = NULL;
86 loop->prepare_handles = NULL;
87 loop->idle_handles = NULL;
89 loop->next_prepare_handle = NULL;
90 loop->next_check_handle = NULL;
91 loop->next_idle_handle = NULL;
93 memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets);
96 RB_INIT(&loop->ares_handles);
98 loop->active_tcp_streams = 0;
99 loop->active_udp_streams = 0;
101 loop->last_err = uv_ok_;
103 memset(&loop->counters, 0, sizeof loop->counters);
107 static void uv_default_loop_init(void) {
108 /* Initialize libuv itself first */
111 /* Initialize the main loop */
112 uv_loop_init(&uv_default_loop_);
116 void uv__once_init(void) {
117 uv_once(&uv_init_guard_, uv_init);
121 uv_loop_t* uv_default_loop(void) {
122 uv_once(&uv_default_loop_init_guard_, uv_default_loop_init);
123 return &uv_default_loop_;
127 uv_loop_t* uv_loop_new(void) {
130 /* Initialize libuv itself first */
133 loop = (uv_loop_t*)malloc(sizeof(uv_loop_t));
136 uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
144 void uv_loop_delete(uv_loop_t* loop) {
145 if (loop != &uv_default_loop_) {
147 for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
148 SOCKET sock = loop->poll_peer_sockets[i];
149 if (sock != 0 && sock != INVALID_SOCKET) {
159 static void uv_poll(uv_loop_t* loop, int block) {
161 DWORD bytes, timeout;
163 OVERLAPPED* overlapped;
167 timeout = uv_get_poll_timeout(loop);
172 success = GetQueuedCompletionStatus(loop->iocp,
179 /* Package was dequeued */
180 req = uv_overlapped_to_req(overlapped);
182 uv_insert_pending_req(loop, req);
184 } else if (GetLastError() != WAIT_TIMEOUT) {
186 uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
191 static void uv_poll_ex(uv_loop_t* loop, int block) {
195 OVERLAPPED_ENTRY overlappeds[128];
200 timeout = uv_get_poll_timeout(loop);
205 assert(pGetQueuedCompletionStatusEx);
207 success = pGetQueuedCompletionStatusEx(loop->iocp,
209 ARRAY_SIZE(overlappeds),
214 for (i = 0; i < count; i++) {
215 /* Package was dequeued */
216 req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
217 uv_insert_pending_req(loop, req);
219 } else if (GetLastError() != WAIT_TIMEOUT) {
221 uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
225 #define UV_LOOP_ALIVE(loop) \
226 ((loop)->active_handles > 0 || \
227 !ngx_queue_empty(&(loop)->active_reqs) || \
228 (loop)->endgame_handles != NULL)
230 #define UV_LOOP_ONCE(loop, poll) \
232 uv_update_time((loop)); \
233 uv_process_timers((loop)); \
235 /* Call idle callbacks if nothing to do. */ \
236 if ((loop)->pending_reqs_tail == NULL && \
237 (loop)->endgame_handles == NULL) { \
238 uv_idle_invoke((loop)); \
241 uv_process_reqs((loop)); \
242 uv_process_endgames((loop)); \
244 if (!UV_LOOP_ALIVE((loop))) { \
248 uv_prepare_invoke((loop)); \
250 poll((loop), (loop)->idle_handles == NULL && \
251 (loop)->pending_reqs_tail == NULL && \
252 (loop)->endgame_handles == NULL && \
253 UV_LOOP_ALIVE((loop))); \
255 uv_check_invoke((loop)); \
258 #define UV_LOOP(loop, poll) \
259 while (UV_LOOP_ALIVE((loop))) { \
260 UV_LOOP_ONCE(loop, poll) \
264 int uv_run_once(uv_loop_t* loop) {
265 if (pGetQueuedCompletionStatusEx) {
266 UV_LOOP_ONCE(loop, uv_poll_ex);
268 UV_LOOP_ONCE(loop, uv_poll);
270 return UV_LOOP_ALIVE(loop);
274 int uv_run(uv_loop_t* loop) {
275 if (pGetQueuedCompletionStatusEx) {
276 UV_LOOP(loop, uv_poll_ex);
278 UV_LOOP(loop, uv_poll);
281 assert(!UV_LOOP_ALIVE((loop)));