kgio 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +2 -0
- data/GIT-VERSION-GEN +1 -1
- data/README +1 -1
- data/ext/kgio/accept.c +14 -1
- data/ext/kgio/autopush.c +45 -0
- data/ext/kgio/connect.c +12 -0
- data/ext/kgio/extconf.rb +1 -0
- data/ext/kgio/kgio.h +4 -0
- data/ext/kgio/kgio_ext.c +1 -0
- data/ext/kgio/poll.c +186 -0
- data/ext/kgio/read_write.c +72 -0
- data/lib/kgio.rb +2 -0
- data/pkg.mk +9 -6
- data/test/test_peek.rb +35 -0
- data/test/test_poll.rb +68 -0
- metadata +11 -4
data/.document
CHANGED
data/GIT-VERSION-GEN
CHANGED
data/README
CHANGED
@@ -33,7 +33,7 @@ applications.
|
|
33
33
|
The library consists of a C extension so you'll need a C compiler
|
34
34
|
and Ruby development libraries/headers.
|
35
35
|
|
36
|
-
You may download the tarball from the
|
36
|
+
You may download the tarball from the Rainbows! project page on Rubyforge
|
37
37
|
and run setup.rb after unpacking it:
|
38
38
|
|
39
39
|
http://rubyforge.org/frs/?group_id=8977
|
data/ext/kgio/accept.c
CHANGED
@@ -248,7 +248,7 @@ static VALUE addr_bang(VALUE io)
|
|
248
248
|
* An optional class argument may be specified to override the
|
249
249
|
* Kgio::Socket-class return value:
|
250
250
|
*
|
251
|
-
* server.
|
251
|
+
* server.kgio_tryaccept(MySocket) -> MySocket
|
252
252
|
*/
|
253
253
|
static VALUE tcp_tryaccept(int argc, VALUE *argv, VALUE io)
|
254
254
|
{
|
@@ -453,13 +453,26 @@ void init_kgio_accept(void)
|
|
453
453
|
rb_define_singleton_method(mKgio, "accept_class=", set_accepted, 1);
|
454
454
|
rb_define_singleton_method(mKgio, "accept_class", get_accepted, 0);
|
455
455
|
|
456
|
+
/*
|
457
|
+
* Document-class: Kgio::UNIXServer
|
458
|
+
*
|
459
|
+
* Kgio::UNIXServer should be used in place of the plain UNIXServer
|
460
|
+
* when kgio_accept and kgio_tryaccept methods are needed.
|
461
|
+
*/
|
456
462
|
cUNIXServer = rb_const_get(rb_cObject, rb_intern("UNIXServer"));
|
457
463
|
cUNIXServer = rb_define_class_under(mKgio, "UNIXServer", cUNIXServer);
|
458
464
|
rb_define_method(cUNIXServer, "kgio_tryaccept", unix_tryaccept, -1);
|
459
465
|
rb_define_method(cUNIXServer, "kgio_accept", unix_accept, -1);
|
460
466
|
|
467
|
+
/*
|
468
|
+
* Document-class: Kgio::TCPServer
|
469
|
+
*
|
470
|
+
* Kgio::TCPServer should be used in place of the plain TCPServer
|
471
|
+
* when kgio_accept and kgio_tryaccept methods are needed.
|
472
|
+
*/
|
461
473
|
cTCPServer = rb_const_get(rb_cObject, rb_intern("TCPServer"));
|
462
474
|
cTCPServer = rb_define_class_under(mKgio, "TCPServer", cTCPServer);
|
475
|
+
|
463
476
|
rb_define_method(cTCPServer, "kgio_tryaccept", tcp_tryaccept, -1);
|
464
477
|
rb_define_method(cTCPServer, "kgio_accept", tcp_accept, -1);
|
465
478
|
init_sock_for_fd();
|
data/ext/kgio/autopush.c
CHANGED
@@ -78,11 +78,32 @@ static void state_set(VALUE io, enum autopush_state state)
|
|
78
78
|
static enum autopush_state detect_acceptor_state(VALUE io);
|
79
79
|
static void push_pending_data(VALUE io);
|
80
80
|
|
81
|
+
/*
|
82
|
+
* call-seq:
|
83
|
+
* Kgio.autopush? -> true or false
|
84
|
+
*
|
85
|
+
* Returns whether or not autopush is enabled.
|
86
|
+
*
|
87
|
+
* Only available on systems with TCP_CORK (Linux) or
|
88
|
+
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
89
|
+
*/
|
81
90
|
static VALUE s_get_autopush(VALUE self)
|
82
91
|
{
|
83
92
|
return enabled ? Qtrue : Qfalse;
|
84
93
|
}
|
85
94
|
|
95
|
+
/*
|
96
|
+
* call-seq:
|
97
|
+
* Kgio.autopush = true
|
98
|
+
* Kgio.autopush = false
|
99
|
+
*
|
100
|
+
* Enables or disables autopush for sockets created with kgio_accept
|
101
|
+
* and kgio_tryaccept methods. Autopush relies on TCP_CORK/TCP_NOPUSH
|
102
|
+
* being enabled on the listen socket.
|
103
|
+
*
|
104
|
+
* Only available on systems with TCP_CORK (Linux) or
|
105
|
+
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
106
|
+
*/
|
86
107
|
static VALUE s_set_autopush(VALUE self, VALUE val)
|
87
108
|
{
|
88
109
|
enabled = RTEST(val);
|
@@ -90,11 +111,35 @@ static VALUE s_set_autopush(VALUE self, VALUE val)
|
|
90
111
|
return val;
|
91
112
|
}
|
92
113
|
|
114
|
+
/*
|
115
|
+
* call-seq:
|
116
|
+
*
|
117
|
+
* io.kgio_autopush? -> true or false
|
118
|
+
*
|
119
|
+
* Returns the current autopush state of the Kgio::SocketMethods-enabled
|
120
|
+
* socket.
|
121
|
+
*
|
122
|
+
* Only available on systems with TCP_CORK (Linux) or
|
123
|
+
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
124
|
+
*/
|
93
125
|
static VALUE autopush_get(VALUE io)
|
94
126
|
{
|
95
127
|
return state_get(io) <= 0 ? Qfalse : Qtrue;
|
96
128
|
}
|
97
129
|
|
130
|
+
/*
|
131
|
+
* call-seq:
|
132
|
+
*
|
133
|
+
* io.kgio_autopush = true
|
134
|
+
* io.kgio_autopush = false
|
135
|
+
*
|
136
|
+
* Enables or disables autopush on any given Kgio::SocketMethods-capable
|
137
|
+
* IO object. This does NOT enable or disable TCP_NOPUSH/TCP_CORK right
|
138
|
+
* away, that must be done with IO.setsockopt
|
139
|
+
*
|
140
|
+
* Only available on systems with TCP_CORK (Linux) or
|
141
|
+
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
142
|
+
*/
|
98
143
|
static VALUE autopush_set(VALUE io, VALUE vbool)
|
99
144
|
{
|
100
145
|
int fd = my_fileno(io);
|
data/ext/kgio/connect.c
CHANGED
@@ -257,12 +257,24 @@ void init_kgio_connect(void)
|
|
257
257
|
rb_define_singleton_method(cKgio_Socket, "new", kgio_connect, 1);
|
258
258
|
rb_define_singleton_method(cKgio_Socket, "start", kgio_start, 1);
|
259
259
|
|
260
|
+
/*
|
261
|
+
* Document-class: Kgio::TCPSocket
|
262
|
+
*
|
263
|
+
* Kgio::TCPSocket should be used in place of the plain TCPSocket
|
264
|
+
* when kgio_* methods are needed.
|
265
|
+
*/
|
260
266
|
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
261
267
|
cTCPSocket = rb_define_class_under(mKgio, "TCPSocket", cTCPSocket);
|
262
268
|
rb_include_module(cTCPSocket, mSocketMethods);
|
263
269
|
rb_define_singleton_method(cTCPSocket, "new", kgio_tcp_connect, 2);
|
264
270
|
rb_define_singleton_method(cTCPSocket, "start", kgio_tcp_start, 2);
|
265
271
|
|
272
|
+
/*
|
273
|
+
* Document-class: Kgio::UNIXSocket
|
274
|
+
*
|
275
|
+
* Kgio::UNIXSocket should be used in place of the plain UNIXSocket
|
276
|
+
* when kgio_* methods are needed.
|
277
|
+
*/
|
266
278
|
cUNIXSocket = rb_const_get(rb_cObject, rb_intern("UNIXSocket"));
|
267
279
|
cUNIXSocket = rb_define_class_under(mKgio, "UNIXSocket", cUNIXSocket);
|
268
280
|
rb_include_module(cUNIXSocket, mSocketMethods);
|
data/ext/kgio/extconf.rb
CHANGED
@@ -2,6 +2,7 @@ require 'mkmf'
|
|
2
2
|
$CPPFLAGS << ' -D_GNU_SOURCE'
|
3
3
|
$CPPFLAGS << ' -DPOSIX_C_SOURCE=1'
|
4
4
|
|
5
|
+
have_func("poll", "poll.h")
|
5
6
|
have_func("getaddrinfo", %w(sys/types.h sys/socket.h netdb.h)) or
|
6
7
|
abort "getaddrinfo required"
|
7
8
|
have_func("getnameinfo", %w(sys/socket.h netdb.h)) or
|
data/ext/kgio/kgio.h
CHANGED
@@ -35,6 +35,7 @@ void init_kgio_read_write(void);
|
|
35
35
|
void init_kgio_accept(void);
|
36
36
|
void init_kgio_connect(void);
|
37
37
|
void init_kgio_autopush(void);
|
38
|
+
void init_kgio_poll(void);
|
38
39
|
|
39
40
|
void kgio_autopush_accept(VALUE, VALUE);
|
40
41
|
void kgio_autopush_recv(VALUE);
|
@@ -42,5 +43,8 @@ void kgio_autopush_send(VALUE);
|
|
42
43
|
|
43
44
|
VALUE kgio_call_wait_writable(VALUE io);
|
44
45
|
VALUE kgio_call_wait_readable(VALUE io);
|
46
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) && defined(HAVE_POLL)
|
47
|
+
# define USE_KGIO_POLL
|
48
|
+
#endif /* USE_KGIO_POLL */
|
45
49
|
|
46
50
|
#endif /* KGIO_H */
|
data/ext/kgio/kgio_ext.c
CHANGED
data/ext/kgio/poll.c
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
#include "kgio.h"
|
2
|
+
#if defined(USE_KGIO_POLL)
|
3
|
+
#include <poll.h>
|
4
|
+
#ifdef HAVE_RUBY_ST_H
|
5
|
+
# include <ruby/st.h>
|
6
|
+
#else
|
7
|
+
# include <st.h>
|
8
|
+
#endif
|
9
|
+
|
10
|
+
static VALUE sym_wait_readable, sym_wait_writable;
|
11
|
+
static ID id_clear;
|
12
|
+
|
13
|
+
struct poll_args {
|
14
|
+
struct pollfd *fds;
|
15
|
+
nfds_t nfds;
|
16
|
+
int timeout;
|
17
|
+
VALUE ios;
|
18
|
+
st_table *fd_to_io;
|
19
|
+
};
|
20
|
+
|
21
|
+
static int num2timeout(VALUE timeout)
|
22
|
+
{
|
23
|
+
switch (TYPE(timeout)) {
|
24
|
+
case T_NIL: return -1;
|
25
|
+
case T_FIXNUM: return FIX2INT(timeout);
|
26
|
+
case T_BIGNUM: return NUM2INT(timeout);
|
27
|
+
}
|
28
|
+
rb_raise(rb_eTypeError, "timeout must be integer or nil");
|
29
|
+
return 0;
|
30
|
+
}
|
31
|
+
|
32
|
+
static VALUE poll_free(VALUE args)
|
33
|
+
{
|
34
|
+
struct poll_args *a = (struct poll_args *)args;
|
35
|
+
|
36
|
+
if (a->fds)
|
37
|
+
xfree(a->fds);
|
38
|
+
if (a->fd_to_io)
|
39
|
+
st_free_table(a->fd_to_io);
|
40
|
+
|
41
|
+
return Qnil;
|
42
|
+
}
|
43
|
+
|
44
|
+
static short value2events(VALUE event)
|
45
|
+
{
|
46
|
+
if (event == sym_wait_readable) return POLLIN;
|
47
|
+
if (event == sym_wait_writable) return POLLOUT;
|
48
|
+
if (TYPE(event) == T_FIXNUM) return (short)FIX2INT(event);
|
49
|
+
rb_raise(rb_eArgError, "unrecognized event");
|
50
|
+
}
|
51
|
+
|
52
|
+
static int io_to_pollfd_i(VALUE key, VALUE value, VALUE args)
|
53
|
+
{
|
54
|
+
struct poll_args *a = (struct poll_args *)args;
|
55
|
+
struct pollfd *pollfd = &a->fds[a->nfds++];
|
56
|
+
|
57
|
+
pollfd->fd = my_fileno(key);
|
58
|
+
pollfd->events = value2events(value);
|
59
|
+
st_insert(a->fd_to_io, (st_data_t)pollfd->fd, (st_data_t)key);
|
60
|
+
return ST_CONTINUE;
|
61
|
+
}
|
62
|
+
|
63
|
+
static void hash2pollfds(struct poll_args *a)
|
64
|
+
{
|
65
|
+
a->fds = xmalloc(sizeof(struct poll_args) * RHASH_SIZE(a->ios));
|
66
|
+
a->fd_to_io = st_init_numtable();
|
67
|
+
rb_hash_foreach(a->ios, io_to_pollfd_i, (VALUE)a);
|
68
|
+
}
|
69
|
+
|
70
|
+
static VALUE nogvl_poll(void *ptr)
|
71
|
+
{
|
72
|
+
struct poll_args *a = ptr;
|
73
|
+
return (VALUE)poll(a->fds, a->nfds, a->timeout);
|
74
|
+
}
|
75
|
+
|
76
|
+
static VALUE poll_result(int nr, struct poll_args *a)
|
77
|
+
{
|
78
|
+
struct pollfd *fds = a->fds;
|
79
|
+
VALUE io;
|
80
|
+
int rc;
|
81
|
+
|
82
|
+
if ((nfds_t)nr != a->nfds)
|
83
|
+
rb_funcall(a->ios, id_clear, 0);
|
84
|
+
for (; nr > 0; fds++) {
|
85
|
+
if (fds->revents == 0)
|
86
|
+
continue;
|
87
|
+
--nr;
|
88
|
+
rc = st_lookup(a->fd_to_io, (st_data_t)fds->fd, &io);
|
89
|
+
assert(rc == 1 && "fd => IO mapping failed");
|
90
|
+
rb_hash_aset(a->ios, io, INT2FIX((int)fds->revents));
|
91
|
+
}
|
92
|
+
return a->ios;
|
93
|
+
}
|
94
|
+
|
95
|
+
static VALUE do_poll(VALUE args)
|
96
|
+
{
|
97
|
+
struct poll_args *a = (struct poll_args *)args;
|
98
|
+
int nr;
|
99
|
+
|
100
|
+
Check_Type(a->ios, T_HASH);
|
101
|
+
hash2pollfds(a);
|
102
|
+
|
103
|
+
nr = (int)rb_thread_blocking_region(nogvl_poll, a, RUBY_UBF_IO, NULL);
|
104
|
+
if (nr < 0) rb_sys_fail("poll");
|
105
|
+
if (nr == 0) return Qnil;
|
106
|
+
|
107
|
+
return poll_result(nr, a);
|
108
|
+
}
|
109
|
+
|
110
|
+
/*
|
111
|
+
* call-seq:
|
112
|
+
*
|
113
|
+
* Kgio.poll({ $stdin => :wait_readable }, 100) -> hash or nil
|
114
|
+
* Kgio.poll({ $stdin => Kgio::POLLIN }, 100) -> hash or nil
|
115
|
+
*
|
116
|
+
* Accepts an input hash with IO objects to wait for as the key and
|
117
|
+
* the events to wait for as its value. The events may either be
|
118
|
+
* +:wait_readable+ or +:wait_writable+ symbols or a Fixnum mask of
|
119
|
+
* Kgio::POLL* constants:
|
120
|
+
*
|
121
|
+
* Kgio::POLLIN - there is data to read
|
122
|
+
* Kgio::POLLPRI - there is urgent data to read
|
123
|
+
* Kgio::POLLOUT - writing will not block
|
124
|
+
* Kgio::POLLRDHUP - peer has shutdown writes (Linux 2.6.17+ only)
|
125
|
+
*
|
126
|
+
* Timeout is specified in Integer milliseconds just like the underlying
|
127
|
+
* poll(2), not in seconds like IO.select. A nil timeout means to wait
|
128
|
+
* forever. It must be an Integer or nil.
|
129
|
+
*
|
130
|
+
* Kgio.poll modifies and returns its input hash on success with the
|
131
|
+
* IO-like object as the key and an Integer mask of events as the hash
|
132
|
+
* value. It can return any of the events specified in the input
|
133
|
+
* above, along with the following events:
|
134
|
+
*
|
135
|
+
* Kgio::POLLERR - error condition occurred on the descriptor
|
136
|
+
* Kgio::POLLHUP - hang up
|
137
|
+
* Kgio::POLLNVAL - invalid request (bad file descriptor)
|
138
|
+
*
|
139
|
+
* This method is only available under Ruby 1.9 or any other
|
140
|
+
* implementations that uses native threads and rb_thread_blocking_region()
|
141
|
+
*/
|
142
|
+
static VALUE s_poll(int argc, VALUE *argv, VALUE self)
|
143
|
+
{
|
144
|
+
VALUE timeout;
|
145
|
+
struct poll_args a;
|
146
|
+
|
147
|
+
rb_scan_args(argc, argv, "11", &a.ios, &timeout);
|
148
|
+
a.timeout = num2timeout(timeout);
|
149
|
+
a.nfds = 0;
|
150
|
+
a.fds = NULL;
|
151
|
+
a.fd_to_io = NULL;
|
152
|
+
|
153
|
+
return rb_ensure(do_poll, (VALUE)&a, poll_free, (VALUE)&a);
|
154
|
+
}
|
155
|
+
|
156
|
+
void init_kgio_poll(void)
|
157
|
+
{
|
158
|
+
VALUE mKgio = rb_define_module("Kgio");
|
159
|
+
rb_define_singleton_method(mKgio, "poll", s_poll, -1);
|
160
|
+
|
161
|
+
sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
|
162
|
+
sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
|
163
|
+
id_clear = rb_intern("clear");
|
164
|
+
|
165
|
+
#define c(x) rb_define_const(mKgio,#x,INT2NUM((int)x))
|
166
|
+
|
167
|
+
/* standard types */
|
168
|
+
|
169
|
+
c(POLLIN);
|
170
|
+
c(POLLPRI);
|
171
|
+
c(POLLOUT);
|
172
|
+
|
173
|
+
#ifdef POLLRDHUP
|
174
|
+
c(POLLRDHUP);
|
175
|
+
#endif
|
176
|
+
|
177
|
+
/* outputs */
|
178
|
+
c(POLLERR);
|
179
|
+
c(POLLHUP);
|
180
|
+
c(POLLNVAL);
|
181
|
+
}
|
182
|
+
#else /* ! USE_KGIO_POLL */
|
183
|
+
void init_kgio_poll(void)
|
184
|
+
{
|
185
|
+
}
|
186
|
+
#endif /* ! USE_KGIO_POLL */
|
data/ext/kgio/read_write.c
CHANGED
@@ -10,6 +10,9 @@ static ID id_set_backtrace;
|
|
10
10
|
*/
|
11
11
|
#if defined(__linux__) && ! defined(USE_MSG_DONTWAIT)
|
12
12
|
# define USE_MSG_DONTWAIT
|
13
|
+
static const int peek_flags = MSG_DONTWAIT|MSG_PEEK;
|
14
|
+
#else
|
15
|
+
static const int peek_flags = MSG_PEEK;
|
13
16
|
#endif
|
14
17
|
|
15
18
|
NORETURN(static void raise_empty_bt(VALUE, const char *));
|
@@ -223,6 +226,72 @@ static VALUE kgio_tryrecv(int argc, VALUE *argv, VALUE io)
|
|
223
226
|
# define kgio_tryrecv kgio_tryread
|
224
227
|
#endif /* USE_MSG_DONTWAIT */
|
225
228
|
|
229
|
+
static VALUE my_peek(int io_wait, int argc, VALUE *argv, VALUE io)
|
230
|
+
{
|
231
|
+
struct io_args a;
|
232
|
+
long n;
|
233
|
+
|
234
|
+
prepare_read(&a, argc, argv, io);
|
235
|
+
kgio_autopush_recv(io);
|
236
|
+
|
237
|
+
if (a.len > 0) {
|
238
|
+
if (peek_flags == MSG_PEEK)
|
239
|
+
set_nonblocking(a.fd);
|
240
|
+
retry:
|
241
|
+
n = (long)recv(a.fd, a.ptr, a.len, peek_flags);
|
242
|
+
if (read_check(&a, n, "recv(MSG_PEEK)", io_wait) != 0)
|
243
|
+
goto retry;
|
244
|
+
}
|
245
|
+
return a.buf;
|
246
|
+
}
|
247
|
+
|
248
|
+
/*
|
249
|
+
* call-seq:
|
250
|
+
*
|
251
|
+
* socket.kgio_trypeek(maxlen) -> buffer
|
252
|
+
* socket.kgio_trypeek(maxlen, buffer) -> buffer
|
253
|
+
*
|
254
|
+
* Like kgio_tryread, except it uses MSG_PEEK so it does not drain the
|
255
|
+
* socket buffer. A subsequent read of any type (including another peek)
|
256
|
+
* will return the same data.
|
257
|
+
*/
|
258
|
+
static VALUE kgio_trypeek(int argc, VALUE *argv, VALUE io)
|
259
|
+
{
|
260
|
+
return my_peek(0, argc, argv, io);
|
261
|
+
}
|
262
|
+
|
263
|
+
/*
|
264
|
+
* call-seq:
|
265
|
+
*
|
266
|
+
* socket.kgio_peek(maxlen) -> buffer
|
267
|
+
* socket.kgio_peek(maxlen, buffer) -> buffer
|
268
|
+
*
|
269
|
+
* Like kgio_read, except it uses MSG_PEEK so it does not drain the
|
270
|
+
* socket buffer. A subsequent read of any type (including another peek)
|
271
|
+
* will return the same data.
|
272
|
+
*/
|
273
|
+
static VALUE kgio_peek(int argc, VALUE *argv, VALUE io)
|
274
|
+
{
|
275
|
+
return my_peek(1, argc, argv, io);
|
276
|
+
}
|
277
|
+
|
278
|
+
/*
|
279
|
+
* call-seq:
|
280
|
+
*
|
281
|
+
* Kgio.trypeek(socket, maxlen) -> buffer
|
282
|
+
* Kgio.trypeek(socket, maxlen, buffer) -> buffer
|
283
|
+
*
|
284
|
+
* Like Kgio.tryread, except it uses MSG_PEEK so it does not drain the
|
285
|
+
* socket buffer. This can only be used on sockets and not pipe objects.
|
286
|
+
* Maybe used in place of SocketMethods#kgio_trypeek for non-Kgio objects
|
287
|
+
*/
|
288
|
+
static VALUE s_trypeek(int argc, VALUE *argv, VALUE mod)
|
289
|
+
{
|
290
|
+
if (argc <= 1)
|
291
|
+
rb_raise(rb_eArgError, "wrong number of arguments");
|
292
|
+
return my_peek(0, argc - 1, &argv[1], argv[0]);
|
293
|
+
}
|
294
|
+
|
226
295
|
static void prepare_write(struct io_args *a, VALUE io, VALUE str)
|
227
296
|
{
|
228
297
|
a->buf = (TYPE(str) == T_STRING) ? str : rb_obj_as_string(str);
|
@@ -410,6 +479,7 @@ void init_kgio_read_write(void)
|
|
410
479
|
|
411
480
|
rb_define_singleton_method(mKgio, "tryread", s_tryread, -1);
|
412
481
|
rb_define_singleton_method(mKgio, "trywrite", s_trywrite, 2);
|
482
|
+
rb_define_singleton_method(mKgio, "trypeek", s_trypeek, -1);
|
413
483
|
|
414
484
|
/*
|
415
485
|
* Document-module: Kgio::PipeMethods
|
@@ -438,6 +508,8 @@ void init_kgio_read_write(void)
|
|
438
508
|
rb_define_method(mSocketMethods, "kgio_write", kgio_send, 1);
|
439
509
|
rb_define_method(mSocketMethods, "kgio_tryread", kgio_tryrecv, -1);
|
440
510
|
rb_define_method(mSocketMethods, "kgio_trywrite", kgio_trysend, 1);
|
511
|
+
rb_define_method(mSocketMethods, "kgio_trypeek", kgio_trypeek, -1);
|
512
|
+
rb_define_method(mSocketMethods, "kgio_peek", kgio_peek, -1);
|
441
513
|
|
442
514
|
/*
|
443
515
|
* Returns the client IPv4 address of the socket in dotted quad
|
data/lib/kgio.rb
CHANGED
data/pkg.mk
CHANGED
@@ -7,7 +7,7 @@ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
|
7
7
|
@./GIT-VERSION-GEN
|
8
8
|
-include GIT-VERSION-FILE
|
9
9
|
-include local.mk
|
10
|
-
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts
|
10
|
+
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts RbConfig::CONFIG["DLEXT"]')
|
11
11
|
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
12
12
|
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
13
13
|
lib := lib
|
@@ -44,24 +44,27 @@ $(ext_dl): $(ext_src) $(ext_pfx_src) $(ext_pfx)/$(ext)/Makefile
|
|
44
44
|
$(MAKE) -C $(@D)
|
45
45
|
lib := $(lib):$(ext_pfx)/$(ext)
|
46
46
|
build: $(ext_dl)
|
47
|
+
else
|
48
|
+
build:
|
47
49
|
endif
|
48
50
|
|
49
|
-
pkg_extra
|
51
|
+
pkg_extra += GIT-VERSION-FILE NEWS ChangeLog LATEST
|
50
52
|
ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
|
51
53
|
$(WRONGDOC) prepare
|
54
|
+
NEWS LATEST: ChangeLog
|
52
55
|
|
53
56
|
manifest:
|
54
57
|
$(RM) .manifest
|
55
58
|
$(MAKE) .manifest
|
56
59
|
|
57
|
-
.manifest:
|
60
|
+
.manifest: $(pkg_extra)
|
58
61
|
(git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
|
59
62
|
LC_ALL=C sort > $@+
|
60
63
|
cmp $@+ $@ || mv $@+ $@
|
61
64
|
$(RM) $@+
|
62
65
|
|
63
|
-
doc:: .document .wrongdoc.yml
|
64
|
-
find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
66
|
+
doc:: .document .wrongdoc.yml $(pkg_extra)
|
67
|
+
-find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
65
68
|
-find ext -type f -name '*.rbc' -exec rm -f '{}' ';'
|
66
69
|
$(RM) -r doc
|
67
70
|
$(WRONGDOC) all
|
@@ -144,7 +147,7 @@ test_units := $(wildcard test/test_*.rb)
|
|
144
147
|
test: test-unit
|
145
148
|
test-unit: $(test_units)
|
146
149
|
$(test_units): build
|
147
|
-
$(RUBY) -I $(lib) $@
|
150
|
+
$(RUBY) -I $(lib) $@ $(RUBY_TEST_OPTS)
|
148
151
|
|
149
152
|
# this requires GNU coreutils variants
|
150
153
|
ifneq ($(RSYNC_DEST),)
|
data/test/test_peek.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$-w = true
|
3
|
+
require 'kgio'
|
4
|
+
|
5
|
+
class TestPeek < Test::Unit::TestCase
|
6
|
+
class EIEIO < Errno::EIO
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
@rd.close
|
11
|
+
@wr.close
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_peek
|
15
|
+
@rd, @wr = Kgio::UNIXSocket.pair
|
16
|
+
@wr.kgio_write "HELLO"
|
17
|
+
assert_equal "HELLO", @rd.kgio_peek(5)
|
18
|
+
assert_equal "HELLO", @rd.kgio_trypeek(5)
|
19
|
+
assert_equal "HELLO", @rd.kgio_read(5)
|
20
|
+
assert_equal :wait_readable, @rd.kgio_trypeek(5)
|
21
|
+
def @rd.kgio_wait_readable
|
22
|
+
raise EIEIO
|
23
|
+
end
|
24
|
+
assert_raises(EIEIO) { @rd.kgio_peek(5) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_peek_singleton
|
28
|
+
@rd, @wr = UNIXSocket.pair
|
29
|
+
@wr.syswrite "HELLO"
|
30
|
+
assert_equal "HELLO", Kgio.trypeek(@rd, 666)
|
31
|
+
assert_equal "HELLO", Kgio.trypeek(@rd, 666)
|
32
|
+
assert_equal "HELLO", Kgio.tryread(@rd, 666)
|
33
|
+
assert_equal :wait_readable, Kgio.trypeek(@rd, 5)
|
34
|
+
end
|
35
|
+
end
|
data/test/test_poll.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$-w = true
|
3
|
+
require 'kgio'
|
4
|
+
|
5
|
+
class TestPoll < Test::Unit::TestCase
|
6
|
+
def teardown
|
7
|
+
[ @rd, @wr ].each { |io| io.close unless io.closed? }
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@rd, @wr = IO.pipe
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_constants
|
15
|
+
assert_kind_of Integer, Kgio::POLLIN
|
16
|
+
assert_kind_of Integer, Kgio::POLLOUT
|
17
|
+
assert_kind_of Integer, Kgio::POLLPRI
|
18
|
+
assert_kind_of Integer, Kgio::POLLHUP
|
19
|
+
assert_kind_of Integer, Kgio::POLLERR
|
20
|
+
assert_kind_of Integer, Kgio::POLLNVAL
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_poll_symbol
|
24
|
+
set = { @rd => :wait_readable, @wr => :wait_writable }
|
25
|
+
res = Kgio.poll(set)
|
26
|
+
assert_equal({@wr => Kgio::POLLOUT}, res)
|
27
|
+
assert_equal set.object_id, res.object_id
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_poll_integer
|
31
|
+
set = { @wr => Kgio::POLLOUT|Kgio::POLLHUP }
|
32
|
+
res = Kgio.poll(set)
|
33
|
+
assert_equal({@wr => Kgio::POLLOUT}, res)
|
34
|
+
assert_equal set.object_id, res.object_id
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_poll_timeout
|
38
|
+
t0 = Time.now
|
39
|
+
res = Kgio.poll({}, 10)
|
40
|
+
diff = Time.now - t0
|
41
|
+
assert diff >= 0.010, "diff=#{diff}"
|
42
|
+
assert_nil res
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_poll_interrupt
|
46
|
+
foo = nil
|
47
|
+
oldquit = trap(:QUIT) { foo = :bar }
|
48
|
+
thr = Thread.new { sleep 0.100; Process.kill(:QUIT, $$) }
|
49
|
+
t0 = Time.now
|
50
|
+
assert_raises(Errno::EINTR) { Kgio.poll({}) }
|
51
|
+
diff = Time.now - t0
|
52
|
+
thr.join
|
53
|
+
assert diff >= 0.010, "diff=#{diff}"
|
54
|
+
ensure
|
55
|
+
trap(:QUIT, "DEFAULT")
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_poll_close
|
59
|
+
foo = nil
|
60
|
+
thr = Thread.new { sleep 0.100; @wr.close }
|
61
|
+
t0 = Time.now
|
62
|
+
res = Kgio.poll({@rd => Kgio::POLLIN})
|
63
|
+
diff = Time.now - t0
|
64
|
+
thr.join
|
65
|
+
assert_equal([ @rd ], res.keys)
|
66
|
+
assert diff >= 0.010, "diff=#{diff}"
|
67
|
+
end
|
68
|
+
end if Kgio.respond_to?(:poll)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kgio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 2.
|
10
|
+
version: 2.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- kgio hackers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-02-
|
18
|
+
date: 2011-02-09 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -69,8 +69,10 @@ extra_rdoc_files:
|
|
69
69
|
- HACKING
|
70
70
|
- lib/kgio.rb
|
71
71
|
- ext/kgio/accept.c
|
72
|
+
- ext/kgio/autopush.c
|
72
73
|
- ext/kgio/connect.c
|
73
74
|
- ext/kgio/kgio_ext.c
|
75
|
+
- ext/kgio/poll.c
|
74
76
|
- ext/kgio/read_write.c
|
75
77
|
- ext/kgio/wait.c
|
76
78
|
files:
|
@@ -101,6 +103,7 @@ files:
|
|
101
103
|
- ext/kgio/missing_accept4.h
|
102
104
|
- ext/kgio/my_fileno.h
|
103
105
|
- ext/kgio/nonblock.h
|
106
|
+
- ext/kgio/poll.c
|
104
107
|
- ext/kgio/read_write.c
|
105
108
|
- ext/kgio/sock_for_fd.h
|
106
109
|
- ext/kgio/wait.c
|
@@ -116,8 +119,10 @@ files:
|
|
116
119
|
- test/test_default_wait.rb
|
117
120
|
- test/test_kgio_addr.rb
|
118
121
|
- test/test_no_dns_on_tcp_connect.rb
|
122
|
+
- test/test_peek.rb
|
119
123
|
- test/test_pipe_popen.rb
|
120
124
|
- test/test_pipe_read_write.rb
|
125
|
+
- test/test_poll.rb
|
121
126
|
- test/test_singleton_read_write.rb
|
122
127
|
- test/test_socketpair_read_write.rb
|
123
128
|
- test/test_tcp6_client_read_server_write.rb
|
@@ -168,6 +173,8 @@ signing_key:
|
|
168
173
|
specification_version: 3
|
169
174
|
summary: kinder, gentler I/O for Ruby
|
170
175
|
test_files:
|
176
|
+
- test/test_poll.rb
|
177
|
+
- test/test_peek.rb
|
171
178
|
- test/test_default_wait.rb
|
172
179
|
- test/test_no_dns_on_tcp_connect.rb
|
173
180
|
- test/test_unix_connect.rb
|