Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
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);
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"))) {
191  }
192  if (mode == ID2SYM(rb_intern("read_write"))) {
194  }
195  if (mode == ID2SYM(rb_intern("readable_writable"))) {
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
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 }
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5425
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5417
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
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
_
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