kgio 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -2
- data/ext/kgio/accept.c +371 -0
- data/ext/kgio/connect.c +256 -0
- data/ext/kgio/kgio.h +40 -0
- data/ext/kgio/kgio_ext.c +6 -1090
- data/ext/kgio/missing/accept4.h +7 -13
- data/ext/kgio/read_write.c +387 -0
- data/ext/kgio/sock_for_fd.h +3 -0
- data/ext/kgio/wait.c +115 -0
- data/lib/kgio.rb +18 -0
- data/test/lib_read_write.rb +22 -4
- metadata +9 -4
data/ext/kgio/missing/accept4.h
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
#
|
2
|
-
# define A4_SOCK_CLOEXEC SOCK_CLOEXEC
|
3
|
-
# define A4_SOCK_NONBLOCK SOCK_NONBLOCK
|
4
|
-
#else
|
1
|
+
#ifndef HAVE_ACCEPT4
|
5
2
|
# ifndef _GNU_SOURCE
|
6
3
|
# define _GNU_SOURCE
|
7
4
|
# endif
|
@@ -9,15 +6,12 @@
|
|
9
6
|
# include <sys/socket.h>
|
10
7
|
# ifndef SOCK_CLOEXEC
|
11
8
|
# if (FD_CLOEXEC == O_NONBLOCK)
|
12
|
-
# define
|
13
|
-
# define
|
9
|
+
# define SOCK_CLOEXEC 1
|
10
|
+
# define SOCK_NONBLOCK 2
|
14
11
|
# else
|
15
|
-
# define
|
16
|
-
# define
|
12
|
+
# define SOCK_CLOEXEC FD_CLOEXEC
|
13
|
+
# define SOCK_NONBLOCK O_NONBLOCK
|
17
14
|
# endif
|
18
|
-
# else
|
19
|
-
# define A4_SOCK_CLOEXEC SOCK_CLOEXEC
|
20
|
-
# define A4_SOCK_NONBLOCK SOCK_NONBLOCK
|
21
15
|
# endif
|
22
16
|
|
23
17
|
/* accept4() is currently a Linux-only goodie */
|
@@ -27,7 +21,7 @@ accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
|
|
27
21
|
int fd = accept(sockfd, addr, addrlen);
|
28
22
|
|
29
23
|
if (fd >= 0) {
|
30
|
-
if ((flags &
|
24
|
+
if ((flags & SOCK_CLOEXEC) == SOCK_CLOEXEC)
|
31
25
|
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
32
26
|
|
33
27
|
/*
|
@@ -36,7 +30,7 @@ accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
|
|
36
30
|
* Linux, so fcntl() is completely unnecessary
|
37
31
|
* in most cases...
|
38
32
|
*/
|
39
|
-
if ((flags &
|
33
|
+
if ((flags & SOCK_NONBLOCK) == SOCK_NONBLOCK) {
|
40
34
|
int fl = fcntl(fd, F_GETFL);
|
41
35
|
|
42
36
|
if ((fl & O_NONBLOCK) == 0)
|
@@ -0,0 +1,387 @@
|
|
1
|
+
#include "kgio.h"
|
2
|
+
static VALUE mKgio_WaitReadable, mKgio_WaitWritable;
|
3
|
+
static VALUE eErrno_EPIPE, eErrno_ECONNRESET;
|
4
|
+
|
5
|
+
/*
|
6
|
+
* we know MSG_DONTWAIT works properly on all stream sockets under Linux
|
7
|
+
* we can define this macro for other platforms as people care and
|
8
|
+
* notice.
|
9
|
+
*/
|
10
|
+
#if defined(__linux__) && ! defined(USE_MSG_DONTWAIT)
|
11
|
+
# define USE_MSG_DONTWAIT
|
12
|
+
#endif
|
13
|
+
|
14
|
+
NORETURN(static void raise_empty_bt(VALUE, const char *));
|
15
|
+
NORETURN(static void my_eof_error(void));
|
16
|
+
NORETURN(static void wr_sys_fail(const char *));
|
17
|
+
|
18
|
+
static void raise_empty_bt(VALUE err, const char *msg)
|
19
|
+
{
|
20
|
+
VALUE exc = rb_exc_new2(err, msg);
|
21
|
+
VALUE bt = rb_ary_new();
|
22
|
+
|
23
|
+
rb_funcall(exc, rb_intern("set_backtrace"), 1, bt);
|
24
|
+
rb_exc_raise(exc);
|
25
|
+
}
|
26
|
+
|
27
|
+
static void my_eof_error(void)
|
28
|
+
{
|
29
|
+
raise_empty_bt(rb_eEOFError, "");
|
30
|
+
}
|
31
|
+
|
32
|
+
static void wr_sys_fail(const char *msg)
|
33
|
+
{
|
34
|
+
switch (errno) {
|
35
|
+
case EPIPE:
|
36
|
+
errno = 0;
|
37
|
+
raise_empty_bt(eErrno_EPIPE, msg);
|
38
|
+
case ECONNRESET:
|
39
|
+
errno = 0;
|
40
|
+
raise_empty_bt(eErrno_ECONNRESET, msg);
|
41
|
+
}
|
42
|
+
rb_sys_fail(msg);
|
43
|
+
}
|
44
|
+
|
45
|
+
static void prepare_read(struct io_args *a, int argc, VALUE *argv, VALUE io)
|
46
|
+
{
|
47
|
+
VALUE length;
|
48
|
+
|
49
|
+
a->io = io;
|
50
|
+
a->fd = my_fileno(io);
|
51
|
+
rb_scan_args(argc, argv, "11", &length, &a->buf);
|
52
|
+
a->len = NUM2LONG(length);
|
53
|
+
if (NIL_P(a->buf)) {
|
54
|
+
a->buf = rb_str_new(NULL, a->len);
|
55
|
+
} else {
|
56
|
+
StringValue(a->buf);
|
57
|
+
rb_str_resize(a->buf, a->len);
|
58
|
+
}
|
59
|
+
a->ptr = RSTRING_PTR(a->buf);
|
60
|
+
}
|
61
|
+
|
62
|
+
static int read_check(struct io_args *a, long n, const char *msg, int io_wait)
|
63
|
+
{
|
64
|
+
if (n == -1) {
|
65
|
+
if (errno == EINTR)
|
66
|
+
return -1;
|
67
|
+
rb_str_set_len(a->buf, 0);
|
68
|
+
if (errno == EAGAIN) {
|
69
|
+
if (io_wait) {
|
70
|
+
kgio_wait_readable(a->io, a->fd);
|
71
|
+
|
72
|
+
/* buf may be modified in other thread/fiber */
|
73
|
+
rb_str_resize(a->buf, a->len);
|
74
|
+
a->ptr = RSTRING_PTR(a->buf);
|
75
|
+
return -1;
|
76
|
+
} else {
|
77
|
+
a->buf = mKgio_WaitReadable;
|
78
|
+
return 0;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
rb_sys_fail(msg);
|
82
|
+
}
|
83
|
+
rb_str_set_len(a->buf, n);
|
84
|
+
if (n == 0)
|
85
|
+
a->buf = Qnil;
|
86
|
+
return 0;
|
87
|
+
}
|
88
|
+
|
89
|
+
static VALUE my_read(int io_wait, int argc, VALUE *argv, VALUE io)
|
90
|
+
{
|
91
|
+
struct io_args a;
|
92
|
+
long n;
|
93
|
+
|
94
|
+
prepare_read(&a, argc, argv, io);
|
95
|
+
set_nonblocking(a.fd);
|
96
|
+
retry:
|
97
|
+
n = (long)read(a.fd, a.ptr, a.len);
|
98
|
+
if (read_check(&a, n, "read", io_wait) != 0)
|
99
|
+
goto retry;
|
100
|
+
return a.buf;
|
101
|
+
}
|
102
|
+
|
103
|
+
/*
|
104
|
+
* call-seq:
|
105
|
+
*
|
106
|
+
* io.kgio_read(maxlen) -> buffer
|
107
|
+
* io.kgio_read(maxlen, buffer) -> buffer
|
108
|
+
*
|
109
|
+
* Reads at most maxlen bytes from the stream socket. Returns with a
|
110
|
+
* newly allocated buffer, or may reuse an existing buffer if supplied.
|
111
|
+
*
|
112
|
+
* Calls the method assigned to Kgio.wait_readable, or blocks in a
|
113
|
+
* thread-safe manner for writability.
|
114
|
+
*
|
115
|
+
* Returns nil on EOF.
|
116
|
+
*
|
117
|
+
* This behaves like read(2) and IO#readpartial, NOT fread(3) or
|
118
|
+
* IO#read which possess read-in-full behavior.
|
119
|
+
*/
|
120
|
+
static VALUE kgio_read(int argc, VALUE *argv, VALUE io)
|
121
|
+
{
|
122
|
+
return my_read(1, argc, argv, io);
|
123
|
+
}
|
124
|
+
|
125
|
+
/*
|
126
|
+
* Same as Kgio::PipeMethods#kgio_read, except EOFError is raised
|
127
|
+
* on EOF without a backtrace
|
128
|
+
*/
|
129
|
+
static VALUE kgio_read_bang(int argc, VALUE *argv, VALUE io)
|
130
|
+
{
|
131
|
+
VALUE rv = my_read(1, argc, argv, io);
|
132
|
+
|
133
|
+
if (NIL_P(rv)) my_eof_error();
|
134
|
+
return rv;
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* call-seq:
|
139
|
+
*
|
140
|
+
* io.kgio_tryread(maxlen) -> buffer
|
141
|
+
* io.kgio_tryread(maxlen, buffer) -> buffer
|
142
|
+
*
|
143
|
+
* Reads at most maxlen bytes from the stream socket. Returns with a
|
144
|
+
* newly allocated buffer, or may reuse an existing buffer if supplied.
|
145
|
+
*
|
146
|
+
* Returns nil on EOF.
|
147
|
+
*
|
148
|
+
* Returns Kgio::WaitReadable if EAGAIN is encountered.
|
149
|
+
*/
|
150
|
+
static VALUE kgio_tryread(int argc, VALUE *argv, VALUE io)
|
151
|
+
{
|
152
|
+
return my_read(0, argc, argv, io);
|
153
|
+
}
|
154
|
+
|
155
|
+
#ifdef USE_MSG_DONTWAIT
|
156
|
+
static VALUE my_recv(int io_wait, int argc, VALUE *argv, VALUE io)
|
157
|
+
{
|
158
|
+
struct io_args a;
|
159
|
+
long n;
|
160
|
+
|
161
|
+
prepare_read(&a, argc, argv, io);
|
162
|
+
retry:
|
163
|
+
n = (long)recv(a.fd, a.ptr, a.len, MSG_DONTWAIT);
|
164
|
+
if (read_check(&a, n, "recv", io_wait) != 0)
|
165
|
+
goto retry;
|
166
|
+
return a.buf;
|
167
|
+
}
|
168
|
+
|
169
|
+
/*
|
170
|
+
* This method may be optimized on some systems (e.g. GNU/Linux) to use
|
171
|
+
* MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
|
172
|
+
* Otherwise this is the same as Kgio::PipeMethods#kgio_read
|
173
|
+
*/
|
174
|
+
static VALUE kgio_recv(int argc, VALUE *argv, VALUE io)
|
175
|
+
{
|
176
|
+
return my_recv(1, argc, argv, io);
|
177
|
+
}
|
178
|
+
|
179
|
+
/*
|
180
|
+
* Same as Kgio::SocketMethods#kgio_read, except EOFError is raised
|
181
|
+
* on EOF without a backtrace
|
182
|
+
*/
|
183
|
+
static VALUE kgio_recv_bang(int argc, VALUE *argv, VALUE io)
|
184
|
+
{
|
185
|
+
VALUE rv = my_recv(1, argc, argv, io);
|
186
|
+
|
187
|
+
if (NIL_P(rv)) my_eof_error();
|
188
|
+
return rv;
|
189
|
+
}
|
190
|
+
|
191
|
+
/*
|
192
|
+
* This method may be optimized on some systems (e.g. GNU/Linux) to use
|
193
|
+
* MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
|
194
|
+
* Otherwise this is the same as Kgio::PipeMethods#kgio_tryread
|
195
|
+
*/
|
196
|
+
static VALUE kgio_tryrecv(int argc, VALUE *argv, VALUE io)
|
197
|
+
{
|
198
|
+
return my_recv(0, argc, argv, io);
|
199
|
+
}
|
200
|
+
#else /* ! USE_MSG_DONTWAIT */
|
201
|
+
# define kgio_recv kgio_read
|
202
|
+
# define kgio_recv_bang kgio_read_bang
|
203
|
+
# define kgio_tryrecv kgio_tryread
|
204
|
+
#endif /* USE_MSG_DONTWAIT */
|
205
|
+
|
206
|
+
static void prepare_write(struct io_args *a, VALUE io, VALUE str)
|
207
|
+
{
|
208
|
+
a->buf = (TYPE(str) == T_STRING) ? str : rb_obj_as_string(str);
|
209
|
+
a->ptr = RSTRING_PTR(a->buf);
|
210
|
+
a->len = RSTRING_LEN(a->buf);
|
211
|
+
a->io = io;
|
212
|
+
a->fd = my_fileno(io);
|
213
|
+
}
|
214
|
+
|
215
|
+
static int write_check(struct io_args *a, long n, const char *msg, int io_wait)
|
216
|
+
{
|
217
|
+
if (a->len == n) {
|
218
|
+
done:
|
219
|
+
a->buf = Qnil;
|
220
|
+
} else if (n == -1) {
|
221
|
+
if (errno == EINTR)
|
222
|
+
return -1;
|
223
|
+
if (errno == EAGAIN) {
|
224
|
+
long written = RSTRING_LEN(a->buf) - a->len;
|
225
|
+
|
226
|
+
if (io_wait) {
|
227
|
+
kgio_wait_writable(a->io, a->fd);
|
228
|
+
|
229
|
+
/* buf may be modified in other thread/fiber */
|
230
|
+
a->len = RSTRING_LEN(a->buf) - written;
|
231
|
+
if (a->len <= 0)
|
232
|
+
goto done;
|
233
|
+
a->ptr = RSTRING_PTR(a->buf) + written;
|
234
|
+
return -1;
|
235
|
+
} else if (written > 0) {
|
236
|
+
a->buf = rb_str_new(a->ptr + n, a->len - n);
|
237
|
+
} else {
|
238
|
+
a->buf = mKgio_WaitWritable;
|
239
|
+
}
|
240
|
+
return 0;
|
241
|
+
}
|
242
|
+
wr_sys_fail(msg);
|
243
|
+
} else {
|
244
|
+
assert(n >= 0 && n < a->len && "write/send syscall broken?");
|
245
|
+
a->ptr += n;
|
246
|
+
a->len -= n;
|
247
|
+
return -1;
|
248
|
+
}
|
249
|
+
return 0;
|
250
|
+
}
|
251
|
+
|
252
|
+
static VALUE my_write(VALUE io, VALUE str, int io_wait)
|
253
|
+
{
|
254
|
+
struct io_args a;
|
255
|
+
long n;
|
256
|
+
|
257
|
+
prepare_write(&a, io, str);
|
258
|
+
set_nonblocking(a.fd);
|
259
|
+
retry:
|
260
|
+
n = (long)write(a.fd, a.ptr, a.len);
|
261
|
+
if (write_check(&a, n, "write", io_wait) != 0)
|
262
|
+
goto retry;
|
263
|
+
return a.buf;
|
264
|
+
}
|
265
|
+
|
266
|
+
/*
|
267
|
+
* call-seq:
|
268
|
+
*
|
269
|
+
* io.kgio_write(str) -> nil
|
270
|
+
*
|
271
|
+
* Returns nil when the write completes.
|
272
|
+
*
|
273
|
+
* Calls the method Kgio.wait_writable if it is set. Otherwise this
|
274
|
+
* blocks in a thread-safe manner until all data is written or a
|
275
|
+
* fatal error occurs.
|
276
|
+
*/
|
277
|
+
static VALUE kgio_write(VALUE io, VALUE str)
|
278
|
+
{
|
279
|
+
return my_write(io, str, 1);
|
280
|
+
}
|
281
|
+
|
282
|
+
/*
|
283
|
+
* call-seq:
|
284
|
+
*
|
285
|
+
* io.kgio_trywrite(str) -> nil or Kgio::WaitWritable
|
286
|
+
*
|
287
|
+
* Returns nil if the write was completed in full.
|
288
|
+
*
|
289
|
+
* Returns a String containing the unwritten portion if EAGAIN
|
290
|
+
* was encountered, but some portion was successfully written.
|
291
|
+
*
|
292
|
+
* Returns Kgio::WaitWritable if EAGAIN is encountered and nothing
|
293
|
+
* was written.
|
294
|
+
*/
|
295
|
+
static VALUE kgio_trywrite(VALUE io, VALUE str)
|
296
|
+
{
|
297
|
+
return my_write(io, str, 0);
|
298
|
+
}
|
299
|
+
|
300
|
+
#ifdef USE_MSG_DONTWAIT
|
301
|
+
/*
|
302
|
+
* This method behaves like Kgio::PipeMethods#kgio_write, except
|
303
|
+
* it will use send(2) with the MSG_DONTWAIT flag on sockets to
|
304
|
+
* avoid unnecessary calls to fcntl(2).
|
305
|
+
*/
|
306
|
+
static VALUE my_send(VALUE io, VALUE str, int io_wait)
|
307
|
+
{
|
308
|
+
struct io_args a;
|
309
|
+
long n;
|
310
|
+
|
311
|
+
prepare_write(&a, io, str);
|
312
|
+
retry:
|
313
|
+
n = (long)send(a.fd, a.ptr, a.len, MSG_DONTWAIT);
|
314
|
+
if (write_check(&a, n, "send", io_wait) != 0)
|
315
|
+
goto retry;
|
316
|
+
return a.buf;
|
317
|
+
}
|
318
|
+
|
319
|
+
/*
|
320
|
+
* This method may be optimized on some systems (e.g. GNU/Linux) to use
|
321
|
+
* MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
|
322
|
+
* Otherwise this is the same as Kgio::PipeMethods#kgio_write
|
323
|
+
*/
|
324
|
+
static VALUE kgio_send(VALUE io, VALUE str)
|
325
|
+
{
|
326
|
+
return my_send(io, str, 1);
|
327
|
+
}
|
328
|
+
|
329
|
+
/*
|
330
|
+
* This method may be optimized on some systems (e.g. GNU/Linux) to use
|
331
|
+
* MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
|
332
|
+
* Otherwise this is the same as Kgio::PipeMethods#kgio_trywrite
|
333
|
+
*/
|
334
|
+
static VALUE kgio_trysend(VALUE io, VALUE str)
|
335
|
+
{
|
336
|
+
return my_send(io, str, 0);
|
337
|
+
}
|
338
|
+
#else /* ! USE_MSG_DONTWAIT */
|
339
|
+
# define kgio_send kgio_write
|
340
|
+
# define kgio_trysend kgio_trywrite
|
341
|
+
#endif /* ! USE_MSG_DONTWAIT */
|
342
|
+
|
343
|
+
void init_kgio_read_write(VALUE mKgio)
|
344
|
+
{
|
345
|
+
VALUE mPipeMethods, mSocketMethods;
|
346
|
+
|
347
|
+
mKgio_WaitReadable = rb_const_get(mKgio, rb_intern("WaitReadable"));
|
348
|
+
mKgio_WaitWritable = rb_const_get(mKgio, rb_intern("WaitWritable"));
|
349
|
+
|
350
|
+
/*
|
351
|
+
* Document-module: Kgio::PipeMethods
|
352
|
+
*
|
353
|
+
* This module may be used used to create classes that respond to
|
354
|
+
* various Kgio methods for reading and writing. This is included
|
355
|
+
* in Kgio::Pipe by default.
|
356
|
+
*/
|
357
|
+
mPipeMethods = rb_define_module_under(mKgio, "PipeMethods");
|
358
|
+
rb_define_method(mPipeMethods, "kgio_read", kgio_read, -1);
|
359
|
+
rb_define_method(mPipeMethods, "kgio_read!", kgio_read_bang, -1);
|
360
|
+
rb_define_method(mPipeMethods, "kgio_write", kgio_write, 1);
|
361
|
+
rb_define_method(mPipeMethods, "kgio_tryread", kgio_tryread, -1);
|
362
|
+
rb_define_method(mPipeMethods, "kgio_trywrite", kgio_trywrite, 1);
|
363
|
+
|
364
|
+
/*
|
365
|
+
* Document-module: Kgio::SocketMethods
|
366
|
+
*
|
367
|
+
* This method behaves like Kgio::PipeMethods, but contains
|
368
|
+
* optimizations for sockets on certain operating systems
|
369
|
+
* (e.g. GNU/Linux).
|
370
|
+
*/
|
371
|
+
mSocketMethods = rb_define_module_under(mKgio, "SocketMethods");
|
372
|
+
rb_define_method(mSocketMethods, "kgio_read", kgio_recv, -1);
|
373
|
+
rb_define_method(mSocketMethods, "kgio_read!", kgio_recv_bang, -1);
|
374
|
+
rb_define_method(mSocketMethods, "kgio_write", kgio_send, 1);
|
375
|
+
rb_define_method(mSocketMethods, "kgio_tryread", kgio_tryrecv, -1);
|
376
|
+
rb_define_method(mSocketMethods, "kgio_trywrite", kgio_trysend, 1);
|
377
|
+
|
378
|
+
/*
|
379
|
+
* Returns the client IPv4 address of the socket in dotted quad
|
380
|
+
* form as a string. This is always the value of the
|
381
|
+
* Kgio::LOCALHOST constant for UNIX domain sockets.
|
382
|
+
*/
|
383
|
+
rb_define_attr(mSocketMethods, "kgio_addr", 1, 1);
|
384
|
+
|
385
|
+
eErrno_EPIPE = rb_const_get(rb_mErrno, rb_intern("EPIPE"));
|
386
|
+
eErrno_ECONNRESET = rb_const_get(rb_mErrno, rb_intern("ECONNRESET"));
|
387
|
+
}
|
data/ext/kgio/sock_for_fd.h
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#ifndef SOCK_FOR_FD_H
|
2
|
+
#define SOCK_FOR_FD_H
|
1
3
|
#include <ruby.h>
|
2
4
|
#ifdef HAVE_RUBY_IO_H
|
3
5
|
# include <ruby/io.h>
|
@@ -64,3 +66,4 @@ static void init_sock_for_fd(void)
|
|
64
66
|
#if SOCK_FOR_FD > 0
|
65
67
|
# define init_sock_for_fd() if (0)
|
66
68
|
#endif
|
69
|
+
#endif /* SOCK_FOR_FD_H */
|
data/ext/kgio/wait.c
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#include "kgio.h"
|
2
|
+
|
3
|
+
static ID io_wait_rd, io_wait_wr;
|
4
|
+
|
5
|
+
void kgio_wait_readable(VALUE io, int fd)
|
6
|
+
{
|
7
|
+
if (io_wait_rd) {
|
8
|
+
(void)rb_funcall(io, io_wait_rd, 0, 0);
|
9
|
+
} else {
|
10
|
+
if (!rb_io_wait_readable(fd))
|
11
|
+
rb_sys_fail("wait readable");
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
void kgio_wait_writable(VALUE io, int fd)
|
16
|
+
{
|
17
|
+
if (io_wait_wr) {
|
18
|
+
(void)rb_funcall(io, io_wait_wr, 0, 0);
|
19
|
+
} else {
|
20
|
+
if (!rb_io_wait_writable(fd))
|
21
|
+
rb_sys_fail("wait writable");
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
/*
|
26
|
+
* call-seq:
|
27
|
+
*
|
28
|
+
* Kgio.wait_readable = :method_name
|
29
|
+
* Kgio.wait_readable = nil
|
30
|
+
*
|
31
|
+
* Sets a method for kgio_read to call when a read would block.
|
32
|
+
* This is useful for non-blocking frameworks that use Fibers,
|
33
|
+
* as the method referred to this may cause the current Fiber
|
34
|
+
* to yield execution.
|
35
|
+
*
|
36
|
+
* A special value of nil will cause Ruby to wait using the
|
37
|
+
* rb_io_wait_readable() function.
|
38
|
+
*/
|
39
|
+
static VALUE set_wait_rd(VALUE mod, VALUE sym)
|
40
|
+
{
|
41
|
+
switch (TYPE(sym)) {
|
42
|
+
case T_SYMBOL:
|
43
|
+
io_wait_rd = SYM2ID(sym);
|
44
|
+
return sym;
|
45
|
+
case T_NIL:
|
46
|
+
io_wait_rd = 0;
|
47
|
+
return sym;
|
48
|
+
}
|
49
|
+
rb_raise(rb_eTypeError, "must be a symbol or nil");
|
50
|
+
return sym;
|
51
|
+
}
|
52
|
+
|
53
|
+
/*
|
54
|
+
* call-seq:
|
55
|
+
*
|
56
|
+
* Kgio.wait_writable = :method_name
|
57
|
+
* Kgio.wait_writable = nil
|
58
|
+
*
|
59
|
+
* Sets a method for kgio_write to call when a read would block.
|
60
|
+
* This is useful for non-blocking frameworks that use Fibers,
|
61
|
+
* as the method referred to this may cause the current Fiber
|
62
|
+
* to yield execution.
|
63
|
+
*
|
64
|
+
* A special value of nil will cause Ruby to wait using the
|
65
|
+
* rb_io_wait_writable() function.
|
66
|
+
*/
|
67
|
+
static VALUE set_wait_wr(VALUE mod, VALUE sym)
|
68
|
+
{
|
69
|
+
switch (TYPE(sym)) {
|
70
|
+
case T_SYMBOL:
|
71
|
+
io_wait_wr = SYM2ID(sym);
|
72
|
+
return sym;
|
73
|
+
case T_NIL:
|
74
|
+
io_wait_wr = 0;
|
75
|
+
return sym;
|
76
|
+
}
|
77
|
+
rb_raise(rb_eTypeError, "must be a symbol or nil");
|
78
|
+
return sym;
|
79
|
+
}
|
80
|
+
|
81
|
+
/*
|
82
|
+
* call-seq:
|
83
|
+
*
|
84
|
+
* Kgio.wait_writable -> Symbol or nil
|
85
|
+
*
|
86
|
+
* Returns the symbolic method name of the method assigned to
|
87
|
+
* call when EAGAIN is occurs on a Kgio::PipeMethods#kgio_write
|
88
|
+
* or Kgio::SocketMethods#kgio_write call
|
89
|
+
*/
|
90
|
+
static VALUE wait_wr(VALUE mod)
|
91
|
+
{
|
92
|
+
return io_wait_wr ? ID2SYM(io_wait_wr) : Qnil;
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
* call-seq:
|
97
|
+
*
|
98
|
+
* Kgio.wait_readable -> Symbol or nil
|
99
|
+
*
|
100
|
+
* Returns the symbolic method name of the method assigned to
|
101
|
+
* call when EAGAIN is occurs on a Kgio::PipeMethods#kgio_read
|
102
|
+
* or Kgio::SocketMethods#kgio_read call.
|
103
|
+
*/
|
104
|
+
static VALUE wait_rd(VALUE mod)
|
105
|
+
{
|
106
|
+
return io_wait_rd ? ID2SYM(io_wait_rd) : Qnil;
|
107
|
+
}
|
108
|
+
|
109
|
+
void init_kgio_wait(VALUE mKgio)
|
110
|
+
{
|
111
|
+
rb_define_singleton_method(mKgio, "wait_readable=", set_wait_rd, 1);
|
112
|
+
rb_define_singleton_method(mKgio, "wait_writable=", set_wait_wr, 1);
|
113
|
+
rb_define_singleton_method(mKgio, "wait_readable", wait_rd, 0);
|
114
|
+
rb_define_singleton_method(mKgio, "wait_writable", wait_wr, 0);
|
115
|
+
}
|