Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

wait.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 io/wait.c -
4
5 $Author$
6 created at: Tue Aug 28 09:08:06 JST 2001
7
8 All the files in this distribution are covered under the Ruby's
9 license (see the file COPYING).
10
11 **********************************************************************/
12
13 #include "ruby.h"
14 #include "ruby/io.h"
15
16 #include <sys/types.h>
17 #if defined(HAVE_UNISTD_H) && (defined(__sun))
18 #include <unistd.h>
19 #endif
20 #if defined(HAVE_SYS_IOCTL_H)
21 #include <sys/ioctl.h>
22 #endif
23 #if defined(FIONREAD_HEADER)
24 #include FIONREAD_HEADER
25 #endif
26
27 #ifdef HAVE_RB_W32_IOCTLSOCKET
28 #define ioctl ioctlsocket
29 #define ioctl_arg u_long
30 #define ioctl_arg2num(i) ULONG2NUM(i)
31 #else
32 #define ioctl_arg int
33 #define ioctl_arg2num(i) INT2NUM(i)
34 #endif
35
36 #ifdef HAVE_RB_W32_IS_SOCKET
37 #define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd)
38 #else
39 #define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
40 #endif
41
42 static VALUE io_ready_p _((VALUE io));
43 static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
44 static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
45 void Init_wait _((void));
46
47 static struct timeval *
48 get_timeout(int argc, VALUE *argv, struct timeval *timerec)
49 {
50 VALUE timeout = Qnil;
51 rb_check_arity(argc, 0, 1);
52 if (!argc || NIL_P(timeout = argv[0])) {
53 return NULL;
54 }
55 else {
56 *timerec = rb_time_interval(timeout);
57 return timerec;
58 }
59 }
60
61 static int
62 wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
63 {
64 int i = rb_wait_for_single_fd(fptr->fd, events, tv);
65 if (i < 0)
66 rb_sys_fail(0);
67 rb_io_check_closed(fptr);
68 return (i & events);
69 }
70
71 /*
72 * call-seq:
73 * io.nread -> int
74 *
75 * Returns number of bytes that can be read without blocking.
76 * Returns zero if no information available.
77 */
78
79 static VALUE
80 io_nread(VALUE io)
81 {
82 rb_io_t *fptr;
83 int len;
84 ioctl_arg n;
85
86 GetOpenFile(io, fptr);
87 rb_io_check_readable(fptr);
88 len = rb_io_read_pending(fptr);
89 if (len > 0) return INT2FIX(len);
90 if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
91 if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
92 if (n > 0) return ioctl_arg2num(n);
93 return INT2FIX(0);
94 }
95
96 /*
97 * call-seq:
98 * io.ready? -> true or false
99 *
100 * Returns true if input available without blocking, or false.
101 */
102
103 static VALUE
104 io_ready_p(VALUE io)
105 {
106 rb_io_t *fptr;
107 struct timeval tv = {0, 0};
108
109 GetOpenFile(io, fptr);
110 rb_io_check_readable(fptr);
111 if (rb_io_read_pending(fptr)) return Qtrue;
112 if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
113 return Qtrue;
114 return Qfalse;
115 }
116
117 /*
118 * call-seq:
119 * io.wait_readable -> IO, true or nil
120 * io.wait_readable(timeout) -> IO, true or nil
121 *
122 * Waits until IO is readable without blocking and returns +self+, or
123 * +nil+ when times out.
124 * Returns +true+ immediately when buffered data is available.
125 */
126
127 static VALUE
128 io_wait_readable(int argc, VALUE *argv, VALUE io)
129 {
130 rb_io_t *fptr;
131 struct timeval timerec;
132 struct timeval *tv;
133
134 GetOpenFile(io, fptr);
135 rb_io_check_readable(fptr);
136 tv = get_timeout(argc, argv, &timerec);
137 if (rb_io_read_pending(fptr)) return Qtrue;
138 if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
139 return io;
140 }
141 return Qnil;
142 }
143
144 /*
145 * call-seq:
146 * io.wait_writable -> IO
147 * io.wait_writable(timeout) -> IO or nil
148 *
149 * Waits until IO is writable without blocking and returns +self+ or
150 * +nil+ when times out.
151 */
152 static VALUE
153 io_wait_writable(int argc, VALUE *argv, VALUE io)
154 {
155 rb_io_t *fptr;
156 struct timeval timerec;
157 struct timeval *tv;
158
159 GetOpenFile(io, fptr);
160 rb_io_check_writable(fptr);
161 tv = get_timeout(argc, argv, &timerec);
162 if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
163 return io;
164 }
165 return Qnil;
166 }
167
168 static int
169 wait_mode_sym(VALUE mode)
170 {
171 if (mode == ID2SYM(rb_intern("r"))) {
172 return RB_WAITFD_IN;
173 }
174 if (mode == ID2SYM(rb_intern("read"))) {
175 return RB_WAITFD_IN;
176 }
177 if (mode == ID2SYM(rb_intern("readable"))) {
178 return RB_WAITFD_IN;
179 }
180 if (mode == ID2SYM(rb_intern("w"))) {
181 return RB_WAITFD_OUT;
182 }
183 if (mode == ID2SYM(rb_intern("write"))) {
184 return RB_WAITFD_OUT;
185 }
186 if (mode == ID2SYM(rb_intern("writable"))) {
187 return RB_WAITFD_OUT;
188 }
189 if (mode == ID2SYM(rb_intern("rw"))) {
190 return RB_WAITFD_IN|RB_WAITFD_OUT;
191 }
192 if (mode == ID2SYM(rb_intern("read_write"))) {
193 return RB_WAITFD_IN|RB_WAITFD_OUT;
194 }
195 if (mode == ID2SYM(rb_intern("readable_writable"))) {
196 return RB_WAITFD_IN|RB_WAITFD_OUT;
197 }
198 rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
199 return 0;
200 }
201
202 /*
203 * call-seq:
204 * io.wait(timeout = nil, mode = :read) -> IO, true or nil
205 *
206 * Waits until IO is readable or writable without blocking and returns
207 * +self+, or +nil+ when times out.
208 * Returns +true+ immediately when buffered data is available.
209 * Optional parameter +mode+ is one of +:read+, +:write+, or
210 * +:read_write+.
211 */
212
213 static VALUE
214 io_wait_readwrite(int argc, VALUE *argv, VALUE io)
215 {
216 rb_io_t *fptr;
217 struct timeval timerec;
218 struct timeval *tv = NULL;
219 int event = 0;
220 int i;
221
222 GetOpenFile(io, fptr);
223 for (i = 0; i < argc; ++i) {
224 if (SYMBOL_P(argv[i])) {
225 event |= wait_mode_sym(argv[i]);
226 }
227 else {
228 *(tv = &timerec) = rb_time_interval(argv[i]);
229 }
230 }
231 /* rb_time_interval() and might_mode() might convert the argument */
232 rb_io_check_closed(fptr);
233 if (!event) event = RB_WAITFD_IN;
234 if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
235 return Qtrue;
236 if (wait_for_single_fd(fptr, event, tv))
237 return io;
238 return Qnil;
239 }
240
241 /*
242 * IO wait methods
243 */
244
245 void
246 Init_wait(void)
247 {
248 rb_define_method(rb_cIO, "nread", io_nread, 0);
249 rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
250 rb_define_method(rb_cIO, "wait", io_wait_readwrite, -1);
251 rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
252 rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
253 }
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
RB_WAITFD_IN
#define RB_WAITFD_IN
Definition: io.h:51
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
rb_intern
#define rb_intern(str)
rb_io_check_closed
void rb_io_check_closed(rb_io_t *)
Definition: io.c:718
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_io_t::fd
int fd
Definition: io.h:68
NULL
#define NULL
Definition: _sdbm.c:101
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
FIONREAD_POSSIBLE_P
#define FIONREAD_POSSIBLE_P(fd)
Definition: wait.c:39
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
RB_WAITFD_OUT
#define RB_WAITFD_OUT
Definition: io.h:53
ioctl_arg2num
#define ioctl_arg2num(i)
Definition: wait.c:33
ruby.h
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:2793
rb_time_interval
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2669
rb_io_check_readable
void rb_io_check_readable(rb_io_t *)
Definition: io.c:899
ioctl
int ioctl(int, int,...)
Definition: win32.c:2811
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
_
void Init_wait _((void))
argv
char ** argv
Definition: ruby.c:223
ioctl_arg
#define ioctl_arg
Definition: wait.c:32
timeval
Definition: missing.h:53
rb_io_check_writable
void rb_io_check_writable(rb_io_t *)
Definition: io.c:923
rb_wait_for_single_fd
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Definition: thread.c:4276
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
io.h
argc
int argc
Definition: ruby.c:222
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:127
Qtrue
#define Qtrue
Definition: ruby.h:468
len
uint8_t len
Definition: escape.c:17
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
rb_io_read_pending
int rb_io_read_pending(rb_io_t *)
Definition: io.c:935
Qnil
#define Qnil
Definition: ruby.h:469
rb_io_t
Definition: io.h:66
rb_cIO
RUBY_EXTERN VALUE rb_cIO
Definition: ruby.h:2030
Init_wait
void Init_wait(void)
Definition: wait.c:246