xref: /libuv/src/win/handle-inl.h (revision 1b01b786)
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
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:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
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
19  * IN THE SOFTWARE.
20  */
21 
22 #ifndef UV_WIN_HANDLE_INL_H_
23 #define UV_WIN_HANDLE_INL_H_
24 
25 #include <assert.h>
26 #include <io.h>
27 
28 #include "uv.h"
29 #include "internal.h"
30 
31 
32 #define DECREASE_ACTIVE_COUNT(loop, handle)                             \
33   do {                                                                  \
34     if (--(handle)->activecnt == 0 &&                                   \
35         !((handle)->flags & UV_HANDLE_CLOSING)) {                       \
36       uv__handle_stop((handle));                                        \
37     }                                                                   \
38     assert((handle)->activecnt >= 0);                                   \
39   } while (0)
40 
41 
42 #define INCREASE_ACTIVE_COUNT(loop, handle)                             \
43   do {                                                                  \
44     if ((handle)->activecnt++ == 0) {                                   \
45       uv__handle_start((handle));                                       \
46     }                                                                   \
47     assert((handle)->activecnt > 0);                                    \
48   } while (0)
49 
50 
51 #define DECREASE_PENDING_REQ_COUNT(handle)                              \
52   do {                                                                  \
53     assert(handle->reqs_pending > 0);                                   \
54     handle->reqs_pending--;                                             \
55                                                                         \
56     if (handle->flags & UV_HANDLE_CLOSING &&                            \
57         handle->reqs_pending == 0) {                                    \
58       uv__want_endgame(loop, (uv_handle_t*)handle);                     \
59     }                                                                   \
60   } while (0)
61 
62 
63 #define uv__handle_closing(handle)                                      \
64   do {                                                                  \
65     assert(!((handle)->flags & UV_HANDLE_CLOSING));                     \
66                                                                         \
67     if (!(((handle)->flags & UV_HANDLE_ACTIVE) &&                       \
68           ((handle)->flags & UV_HANDLE_REF)))                           \
69       uv__active_handle_add((uv_handle_t*) (handle));                   \
70                                                                         \
71     (handle)->flags |= UV_HANDLE_CLOSING;                               \
72     (handle)->flags &= ~UV_HANDLE_ACTIVE;                               \
73   } while (0)
74 
75 
76 #define uv__handle_close(handle)                                        \
77   do {                                                                  \
78     uv__queue_remove(&(handle)->handle_queue);                          \
79     uv__active_handle_rm((uv_handle_t*) (handle));                      \
80                                                                         \
81     (handle)->flags |= UV_HANDLE_CLOSED;                                \
82                                                                         \
83     if ((handle)->close_cb)                                             \
84       (handle)->close_cb((uv_handle_t*) (handle));                      \
85   } while (0)
86 
87 
uv__want_endgame(uv_loop_t * loop,uv_handle_t * handle)88 INLINE static void uv__want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
89   if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) {
90     handle->flags |= UV_HANDLE_ENDGAME_QUEUED;
91 
92     handle->endgame_next = loop->endgame_handles;
93     loop->endgame_handles = handle;
94   }
95 }
96 
97 
uv__process_endgames(uv_loop_t * loop)98 INLINE static void uv__process_endgames(uv_loop_t* loop) {
99   uv_handle_t* handle;
100 
101   while (loop->endgame_handles) {
102     handle = loop->endgame_handles;
103     loop->endgame_handles = handle->endgame_next;
104 
105     handle->flags &= ~UV_HANDLE_ENDGAME_QUEUED;
106 
107     switch (handle->type) {
108       case UV_TCP:
109         uv__tcp_endgame(loop, (uv_tcp_t*) handle);
110         break;
111 
112       case UV_NAMED_PIPE:
113         uv__pipe_endgame(loop, (uv_pipe_t*) handle);
114         break;
115 
116       case UV_TTY:
117         uv__tty_endgame(loop, (uv_tty_t*) handle);
118         break;
119 
120       case UV_UDP:
121         uv__udp_endgame(loop, (uv_udp_t*) handle);
122         break;
123 
124       case UV_POLL:
125         uv__poll_endgame(loop, (uv_poll_t*) handle);
126         break;
127 
128       case UV_TIMER:
129         uv__timer_close((uv_timer_t*) handle);
130         uv__handle_close(handle);
131         break;
132 
133       case UV_PREPARE:
134       case UV_CHECK:
135       case UV_IDLE:
136         uv__loop_watcher_endgame(loop, handle);
137         break;
138 
139       case UV_ASYNC:
140         uv__async_endgame(loop, (uv_async_t*) handle);
141         break;
142 
143       case UV_SIGNAL:
144         uv__signal_endgame(loop, (uv_signal_t*) handle);
145         break;
146 
147       case UV_PROCESS:
148         uv__process_endgame(loop, (uv_process_t*) handle);
149         break;
150 
151       case UV_FS_EVENT:
152         uv__fs_event_endgame(loop, (uv_fs_event_t*) handle);
153         break;
154 
155       case UV_FS_POLL:
156         uv__fs_poll_endgame(loop, (uv_fs_poll_t*) handle);
157         break;
158 
159       default:
160         assert(0);
161         break;
162     }
163   }
164 }
165 
uv__get_osfhandle(int fd)166 INLINE static HANDLE uv__get_osfhandle(int fd)
167 {
168   /* _get_osfhandle() raises an assert in debug builds if the FD is invalid.
169    * But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for
170    * invalid FDs in release builds (or if you let the assert continue). So this
171    * wrapper function disables asserts when calling _get_osfhandle. */
172 
173   HANDLE handle;
174   UV_BEGIN_DISABLE_CRT_ASSERT();
175   handle = (HANDLE) _get_osfhandle(fd);
176   UV_END_DISABLE_CRT_ASSERT();
177   return handle;
178 }
179 
180 #endif /* UV_WIN_HANDLE_INL_H_ */
181