kgio 2.8.1 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/kgio/read.c ADDED
@@ -0,0 +1,328 @@
1
+ /* ref: rubinius b2811f260de16d1e972462e27852470364608de5 */
2
+ #define RSTRING_MODIFIED 1
3
+ #include "kgio.h"
4
+ #include "my_fileno.h"
5
+ #include "nonblock.h"
6
+ static VALUE sym_wait_readable;
7
+
8
+ #ifdef USE_MSG_DONTWAIT
9
+ static const int peek_flags = MSG_DONTWAIT|MSG_PEEK;
10
+
11
+ /* we don't need these variants, we call kgio_autopush_recv directly */
12
+ static inline void kgio_autopush_read(VALUE io) { }
13
+
14
+ #else
15
+ static const int peek_flags = MSG_PEEK;
16
+ static inline void kgio_autopush_read(VALUE io) { kgio_autopush_recv(io); }
17
+ #endif
18
+
19
+ struct rd_args {
20
+ VALUE io;
21
+ VALUE buf;
22
+ char *ptr;
23
+ long len;
24
+ int fd;
25
+ };
26
+
27
+ NORETURN(static void my_eof_error(void));
28
+
29
+ static void my_eof_error(void)
30
+ {
31
+ kgio_raise_empty_bt(rb_eEOFError, "end of file reached");
32
+ }
33
+
34
+ static void prepare_read(struct rd_args *a, int argc, VALUE *argv, VALUE io)
35
+ {
36
+ VALUE length;
37
+
38
+ a->io = io;
39
+ a->fd = my_fileno(io);
40
+ rb_scan_args(argc, argv, "11", &length, &a->buf);
41
+ a->len = NUM2LONG(length);
42
+ if (NIL_P(a->buf)) {
43
+ a->buf = rb_str_new(NULL, a->len);
44
+ } else {
45
+ StringValue(a->buf);
46
+ rb_str_modify(a->buf);
47
+ rb_str_resize(a->buf, a->len);
48
+ }
49
+ a->ptr = RSTRING_PTR(a->buf);
50
+ }
51
+
52
+ static int read_check(struct rd_args *a, long n, const char *msg, int io_wait)
53
+ {
54
+ if (n < 0) {
55
+ if (errno == EINTR) {
56
+ a->fd = my_fileno(a->io);
57
+ return -1;
58
+ }
59
+ rb_str_set_len(a->buf, 0);
60
+ if (errno == EAGAIN) {
61
+ if (io_wait) {
62
+ (void)kgio_call_wait_readable(a->io);
63
+
64
+ /* buf may be modified in other thread/fiber */
65
+ rb_str_modify(a->buf);
66
+ rb_str_resize(a->buf, a->len);
67
+ a->ptr = RSTRING_PTR(a->buf);
68
+ return -1;
69
+ } else {
70
+ a->buf = sym_wait_readable;
71
+ return 0;
72
+ }
73
+ }
74
+ kgio_rd_sys_fail(msg);
75
+ }
76
+ rb_str_set_len(a->buf, n);
77
+ if (n == 0)
78
+ a->buf = Qnil;
79
+ return 0;
80
+ }
81
+
82
+ static VALUE my_read(int io_wait, int argc, VALUE *argv, VALUE io)
83
+ {
84
+ struct rd_args a;
85
+ long n;
86
+
87
+ prepare_read(&a, argc, argv, io);
88
+ kgio_autopush_read(io);
89
+
90
+ if (a.len > 0) {
91
+ set_nonblocking(a.fd);
92
+ retry:
93
+ n = (long)read(a.fd, a.ptr, a.len);
94
+ if (read_check(&a, n, "read", io_wait) != 0)
95
+ goto retry;
96
+ }
97
+ return a.buf;
98
+ }
99
+
100
+ /*
101
+ * call-seq:
102
+ *
103
+ * io.kgio_read(maxlen) -> buffer
104
+ * io.kgio_read(maxlen, buffer) -> buffer
105
+ *
106
+ * Reads at most maxlen bytes from the stream socket. Returns with a
107
+ * newly allocated buffer, or may reuse an existing buffer if supplied.
108
+ *
109
+ * This may block and call any method defined to +kgio_wait_readable+
110
+ * for the class.
111
+ *
112
+ * Returns nil on EOF.
113
+ *
114
+ * This behaves like read(2) and IO#readpartial, NOT fread(3) or
115
+ * IO#read which possess read-in-full behavior.
116
+ */
117
+ static VALUE kgio_read(int argc, VALUE *argv, VALUE io)
118
+ {
119
+ return my_read(1, argc, argv, io);
120
+ }
121
+
122
+ /*
123
+ * Same as Kgio::PipeMethods#kgio_read, except EOFError is raised
124
+ * on EOF without a backtrace. This method is intended as a
125
+ * drop-in replacement for places where IO#readpartial is used, and
126
+ * may be aliased as such.
127
+ */
128
+ static VALUE kgio_read_bang(int argc, VALUE *argv, VALUE io)
129
+ {
130
+ VALUE rv = my_read(1, argc, argv, io);
131
+
132
+ if (NIL_P(rv)) my_eof_error();
133
+ return rv;
134
+ }
135
+
136
+ /*
137
+ * call-seq:
138
+ *
139
+ * io.kgio_tryread(maxlen) -> buffer
140
+ * io.kgio_tryread(maxlen, buffer) -> buffer
141
+ *
142
+ * Reads at most maxlen bytes from the stream socket. Returns with a
143
+ * newly allocated buffer, or may reuse an existing buffer if supplied.
144
+ *
145
+ * Returns nil on EOF.
146
+ *
147
+ * Returns :wait_readable if EAGAIN is encountered.
148
+ */
149
+ static VALUE kgio_tryread(int argc, VALUE *argv, VALUE io)
150
+ {
151
+ return my_read(0, argc, argv, io);
152
+ }
153
+
154
+ #ifdef USE_MSG_DONTWAIT
155
+ static VALUE my_recv(int io_wait, int argc, VALUE *argv, VALUE io)
156
+ {
157
+ struct rd_args a;
158
+ long n;
159
+
160
+ prepare_read(&a, argc, argv, io);
161
+ kgio_autopush_recv(io);
162
+
163
+ if (a.len > 0) {
164
+ retry:
165
+ n = (long)recv(a.fd, a.ptr, a.len, MSG_DONTWAIT);
166
+ if (read_check(&a, n, "recv", io_wait) != 0)
167
+ goto retry;
168
+ }
169
+ return a.buf;
170
+ }
171
+
172
+ /*
173
+ * This method may be optimized on some systems (e.g. GNU/Linux) to use
174
+ * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
175
+ * Otherwise this is the same as Kgio::PipeMethods#kgio_read
176
+ */
177
+ static VALUE kgio_recv(int argc, VALUE *argv, VALUE io)
178
+ {
179
+ return my_recv(1, argc, argv, io);
180
+ }
181
+
182
+ /*
183
+ * Same as Kgio::SocketMethods#kgio_read, except EOFError is raised
184
+ * on EOF without a backtrace
185
+ */
186
+ static VALUE kgio_recv_bang(int argc, VALUE *argv, VALUE io)
187
+ {
188
+ VALUE rv = my_recv(1, argc, argv, io);
189
+
190
+ if (NIL_P(rv)) my_eof_error();
191
+ return rv;
192
+ }
193
+
194
+ /*
195
+ * This method may be optimized on some systems (e.g. GNU/Linux) to use
196
+ * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
197
+ * Otherwise this is the same as Kgio::PipeMethods#kgio_tryread
198
+ */
199
+ static VALUE kgio_tryrecv(int argc, VALUE *argv, VALUE io)
200
+ {
201
+ return my_recv(0, argc, argv, io);
202
+ }
203
+ #else /* ! USE_MSG_DONTWAIT */
204
+ # define kgio_recv kgio_read
205
+ # define kgio_recv_bang kgio_read_bang
206
+ # define kgio_tryrecv kgio_tryread
207
+ #endif /* USE_MSG_DONTWAIT */
208
+
209
+ static VALUE my_peek(int io_wait, int argc, VALUE *argv, VALUE io)
210
+ {
211
+ struct rd_args a;
212
+ long n;
213
+
214
+ prepare_read(&a, argc, argv, io);
215
+ kgio_autopush_recv(io);
216
+
217
+ if (a.len > 0) {
218
+ if (peek_flags == MSG_PEEK)
219
+ set_nonblocking(a.fd);
220
+ retry:
221
+ n = (long)recv(a.fd, a.ptr, a.len, peek_flags);
222
+ if (read_check(&a, n, "recv(MSG_PEEK)", io_wait) != 0)
223
+ goto retry;
224
+ }
225
+ return a.buf;
226
+ }
227
+
228
+ /*
229
+ * call-seq:
230
+ *
231
+ * socket.kgio_trypeek(maxlen) -> buffer
232
+ * socket.kgio_trypeek(maxlen, buffer) -> buffer
233
+ *
234
+ * Like kgio_tryread, except it uses MSG_PEEK so it does not drain the
235
+ * socket buffer. A subsequent read of any type (including another peek)
236
+ * will return the same data.
237
+ */
238
+ static VALUE kgio_trypeek(int argc, VALUE *argv, VALUE io)
239
+ {
240
+ return my_peek(0, argc, argv, io);
241
+ }
242
+
243
+ /*
244
+ * call-seq:
245
+ *
246
+ * socket.kgio_peek(maxlen) -> buffer
247
+ * socket.kgio_peek(maxlen, buffer) -> buffer
248
+ *
249
+ * Like kgio_read, except it uses MSG_PEEK so it does not drain the
250
+ * socket buffer. A subsequent read of any type (including another peek)
251
+ * will return the same data.
252
+ */
253
+ static VALUE kgio_peek(int argc, VALUE *argv, VALUE io)
254
+ {
255
+ return my_peek(1, argc, argv, io);
256
+ }
257
+
258
+ /*
259
+ * call-seq:
260
+ *
261
+ * Kgio.trypeek(socket, maxlen) -> buffer
262
+ * Kgio.trypeek(socket, maxlen, buffer) -> buffer
263
+ *
264
+ * Like Kgio.tryread, except it uses MSG_PEEK so it does not drain the
265
+ * socket buffer. This can only be used on sockets and not pipe objects.
266
+ * Maybe used in place of SocketMethods#kgio_trypeek for non-Kgio objects
267
+ */
268
+ static VALUE s_trypeek(int argc, VALUE *argv, VALUE mod)
269
+ {
270
+ if (argc <= 1)
271
+ rb_raise(rb_eArgError, "wrong number of arguments");
272
+ return my_peek(0, argc - 1, &argv[1], argv[0]);
273
+ }
274
+
275
+ /*
276
+ * call-seq:
277
+ *
278
+ * Kgio.tryread(io, maxlen) -> buffer
279
+ * Kgio.tryread(io, maxlen, buffer) -> buffer
280
+ *
281
+ * Returns nil on EOF.
282
+ * Returns :wait_readable if EAGAIN is encountered.
283
+ *
284
+ * Maybe used in place of PipeMethods#kgio_tryread for non-Kgio objects
285
+ */
286
+ static VALUE s_tryread(int argc, VALUE *argv, VALUE mod)
287
+ {
288
+ if (argc <= 1)
289
+ rb_raise(rb_eArgError, "wrong number of arguments");
290
+ return my_read(0, argc - 1, &argv[1], argv[0]);
291
+ }
292
+
293
+ void init_kgio_read(void)
294
+ {
295
+ VALUE mPipeMethods, mSocketMethods;
296
+ VALUE mKgio = rb_define_module("Kgio");
297
+
298
+ sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
299
+
300
+ rb_define_singleton_method(mKgio, "tryread", s_tryread, -1);
301
+ rb_define_singleton_method(mKgio, "trypeek", s_trypeek, -1);
302
+
303
+ /*
304
+ * Document-module: Kgio::PipeMethods
305
+ *
306
+ * This module may be used used to create classes that respond to
307
+ * various Kgio methods for reading and writing. This is included
308
+ * in Kgio::Pipe by default.
309
+ */
310
+ mPipeMethods = rb_define_module_under(mKgio, "PipeMethods");
311
+ rb_define_method(mPipeMethods, "kgio_read", kgio_read, -1);
312
+ rb_define_method(mPipeMethods, "kgio_read!", kgio_read_bang, -1);
313
+ rb_define_method(mPipeMethods, "kgio_tryread", kgio_tryread, -1);
314
+
315
+ /*
316
+ * Document-module: Kgio::SocketMethods
317
+ *
318
+ * This method behaves like Kgio::PipeMethods, but contains
319
+ * optimizations for sockets on certain operating systems
320
+ * (e.g. GNU/Linux).
321
+ */
322
+ mSocketMethods = rb_define_module_under(mKgio, "SocketMethods");
323
+ rb_define_method(mSocketMethods, "kgio_read", kgio_recv, -1);
324
+ rb_define_method(mSocketMethods, "kgio_read!", kgio_recv_bang, -1);
325
+ rb_define_method(mSocketMethods, "kgio_tryread", kgio_tryrecv, -1);
326
+ rb_define_method(mSocketMethods, "kgio_trypeek", kgio_trypeek, -1);
327
+ rb_define_method(mSocketMethods, "kgio_peek", kgio_peek, -1);
328
+ }
@@ -1,3 +1,4 @@
1
+ /* We do not modify RSTRING in this file, so RSTRING_MODIFIED is not needed */
1
2
  #if defined(HAVE_RB_IO_T) && \
2
3
  defined(HAVE_TYPE_STRUCT_RFILE) && \
3
4
  defined(HAVE_ST_PATHV)
data/ext/kgio/tryopen.c CHANGED
@@ -1,3 +1,4 @@
1
+ /* We do not modify RSTRING in this file, so RSTRING_MODIFIED is not needed */
1
2
  #include <ruby.h>
2
3
  #ifdef HAVE_RUBY_IO_H
3
4
  # include <ruby/io.h>
@@ -17,6 +18,7 @@
17
18
  #include <errno.h>
18
19
  #include "set_file_path.h"
19
20
  #include "ancient_ruby.h"
21
+ #include "kgio.h"
20
22
 
21
23
  static ID id_for_fd, id_to_path, id_path;
22
24
  static st_table *errno2sym;
@@ -38,7 +40,7 @@ static VALUE nogvl_open(void *ptr)
38
40
  return (VALUE)rb_cloexec_open(o->pathname, o->flags, o->mode);
39
41
  }
40
42
 
41
- #ifndef HAVE_RB_THREAD_BLOCKING_REGION
43
+ #ifndef KGIO_HAVE_THREAD_CALL_WITHOUT_GVL
42
44
  # define RUBY_UBF_IO ((void *)(-1))
43
45
  # include "rubysig.h"
44
46
  typedef void rb_unblock_function_t(void *);
@@ -57,7 +59,7 @@ static VALUE my_thread_blocking_region(
57
59
  }
58
60
  #define rb_thread_blocking_region(fn,data1,ubf,data2) \
59
61
  my_thread_blocking_region((fn),(data1),(ubf),(data2))
60
- #endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
62
+ #endif /* ! KGIO_HAVE_THREAD_CALL_WITHOUT_GVL */
61
63
 
62
64
  /*
63
65
  * call-seq:
@@ -80,7 +82,7 @@ static VALUE my_thread_blocking_region(
80
82
  */
81
83
  static VALUE s_tryopen(int argc, VALUE *argv, VALUE klass)
82
84
  {
83
- int fd;
85
+ long fd;
84
86
  VALUE pathname, flags, mode;
85
87
  struct open_args o;
86
88
  int retried = 0;
@@ -105,7 +107,7 @@ static VALUE s_tryopen(int argc, VALUE *argv, VALUE klass)
105
107
  }
106
108
 
107
109
  retry:
108
- fd = (int)rb_thread_blocking_region(nogvl_open, &o, RUBY_UBF_IO, 0);
110
+ fd = (long)rb_thread_blocking_region(nogvl_open, &o, RUBY_UBF_IO, 0);
109
111
  if (fd < 0) {
110
112
  if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
111
113
  rb_gc();
@@ -124,7 +126,7 @@ retry:
124
126
  return rv;
125
127
  }
126
128
  }
127
- rv = rb_funcall(klass, id_for_fd, 1, INT2FIX(fd));
129
+ rv = rb_funcall(klass, id_for_fd, 1, LONG2FIX(fd));
128
130
  set_file_path(rv, pathname);
129
131
  return rv;
130
132
  }
@@ -135,8 +137,7 @@ void init_kgio_tryopen(void)
135
137
  VALUE mPipeMethods = rb_const_get(mKgio, rb_intern("PipeMethods"));
136
138
  VALUE cFile;
137
139
  VALUE tmp;
138
- VALUE *ptr;
139
- long len;
140
+ long i, len;
140
141
 
141
142
  id_path = rb_intern("path");
142
143
  id_for_fd = rb_intern("for_fd");
@@ -161,16 +162,22 @@ void init_kgio_tryopen(void)
161
162
 
162
163
  errno2sym = st_init_numtable();
163
164
  tmp = rb_funcall(rb_mErrno, rb_intern("constants"), 0);
164
- ptr = RARRAY_PTR(tmp);
165
165
  len = RARRAY_LEN(tmp);
166
- for (; --len >= 0; ptr++) {
166
+ for (i = 0; i < len; i++) {
167
167
  VALUE error;
168
+ VALUE err = rb_ary_entry(tmp, i);
168
169
  ID const_id;
169
170
 
170
- switch (TYPE(*ptr)) {
171
- case T_SYMBOL: const_id = SYM2ID(*ptr); break;
172
- case T_STRING: const_id = rb_intern(RSTRING_PTR(*ptr)); break;
173
- default: rb_bug("constant not a symbol or string");
171
+ switch (TYPE(err)) {
172
+ case T_SYMBOL: const_id = SYM2ID(err); break;
173
+ case T_STRING: const_id = rb_intern(RSTRING_PTR(err)); break;
174
+ default: {
175
+ VALUE i = rb_inspect(err);
176
+ const char *s = RSTRING_PTR(i);
177
+
178
+ rb_bug("constant not a symbol or string: %s", s);
179
+ RB_GC_GUARD(i);
180
+ }
174
181
  }
175
182
 
176
183
  error = rb_const_get(rb_mErrno, const_id);
data/ext/kgio/write.c ADDED
@@ -0,0 +1,267 @@
1
+ /* we do not modify RSTRING pointers here */
2
+ #include "kgio.h"
3
+ #include "my_fileno.h"
4
+ #include "nonblock.h"
5
+ static VALUE sym_wait_writable;
6
+
7
+ /* prefer rb_str_subseq because we don't use negative offsets */
8
+ #ifndef HAVE_RB_STR_SUBSEQ
9
+ #define rb_str_subseq rb_str_substr
10
+ #endif
11
+
12
+ struct wr_args {
13
+ VALUE io;
14
+ VALUE buf;
15
+ const char *ptr;
16
+ long len;
17
+ int fd;
18
+ int flags;
19
+ };
20
+
21
+ static void prepare_write(struct wr_args *a, VALUE io, VALUE str)
22
+ {
23
+ a->buf = (TYPE(str) == T_STRING) ? str : rb_obj_as_string(str);
24
+ a->ptr = RSTRING_PTR(a->buf);
25
+ a->len = RSTRING_LEN(a->buf);
26
+ a->io = io;
27
+ a->fd = my_fileno(io);
28
+ }
29
+
30
+ static int write_check(struct wr_args *a, long n, const char *msg, int io_wait)
31
+ {
32
+ if (a->len == n) {
33
+ done:
34
+ a->buf = Qnil;
35
+ } else if (n < 0) {
36
+ if (errno == EINTR) {
37
+ a->fd = my_fileno(a->io);
38
+ return -1;
39
+ }
40
+ if (errno == EAGAIN) {
41
+ long written = RSTRING_LEN(a->buf) - a->len;
42
+
43
+ if (io_wait) {
44
+ (void)kgio_call_wait_writable(a->io);
45
+
46
+ /* buf may be modified in other thread/fiber */
47
+ a->len = RSTRING_LEN(a->buf) - written;
48
+ if (a->len <= 0)
49
+ goto done;
50
+ a->ptr = RSTRING_PTR(a->buf) + written;
51
+ return -1;
52
+ } else if (written > 0) {
53
+ a->buf = rb_str_subseq(a->buf, written, a->len);
54
+ } else {
55
+ a->buf = sym_wait_writable;
56
+ }
57
+ return 0;
58
+ }
59
+ kgio_wr_sys_fail(msg);
60
+ } else {
61
+ assert(n >= 0 && n < a->len && "write/send syscall broken?");
62
+ a->ptr += n;
63
+ a->len -= n;
64
+ return -1;
65
+ }
66
+ return 0;
67
+ }
68
+
69
+ static VALUE my_write(VALUE io, VALUE str, int io_wait)
70
+ {
71
+ struct wr_args a;
72
+ long n;
73
+
74
+ prepare_write(&a, io, str);
75
+ set_nonblocking(a.fd);
76
+ retry:
77
+ n = (long)write(a.fd, a.ptr, a.len);
78
+ if (write_check(&a, n, "write", io_wait) != 0)
79
+ goto retry;
80
+ if (TYPE(a.buf) != T_SYMBOL)
81
+ kgio_autopush_write(io);
82
+ return a.buf;
83
+ }
84
+
85
+ /*
86
+ * call-seq:
87
+ *
88
+ * io.kgio_write(str) -> nil
89
+ *
90
+ * Returns nil when the write completes.
91
+ *
92
+ * This may block and call any method defined to +kgio_wait_writable+
93
+ * for the class.
94
+ */
95
+ static VALUE kgio_write(VALUE io, VALUE str)
96
+ {
97
+ return my_write(io, str, 1);
98
+ }
99
+
100
+ /*
101
+ * call-seq:
102
+ *
103
+ * io.kgio_trywrite(str) -> nil, String or :wait_writable
104
+ *
105
+ * Returns nil if the write was completed in full.
106
+ *
107
+ * Returns a String containing the unwritten portion if EAGAIN
108
+ * was encountered, but some portion was successfully written.
109
+ *
110
+ * Returns :wait_writable if EAGAIN is encountered and nothing
111
+ * was written.
112
+ */
113
+ static VALUE kgio_trywrite(VALUE io, VALUE str)
114
+ {
115
+ return my_write(io, str, 0);
116
+ }
117
+
118
+ #ifdef USE_MSG_DONTWAIT
119
+ /*
120
+ * This method behaves like Kgio::PipeMethods#kgio_write, except
121
+ * it will use send(2) with the MSG_DONTWAIT flag on sockets to
122
+ * avoid unnecessary calls to fcntl(2).
123
+ */
124
+ static VALUE my_send(VALUE io, VALUE str, int io_wait)
125
+ {
126
+ struct wr_args a;
127
+ long n;
128
+
129
+ prepare_write(&a, io, str);
130
+ retry:
131
+ n = (long)send(a.fd, a.ptr, a.len, MSG_DONTWAIT);
132
+ if (write_check(&a, n, "send", io_wait) != 0)
133
+ goto retry;
134
+ if (TYPE(a.buf) != T_SYMBOL)
135
+ kgio_autopush_send(io);
136
+ return a.buf;
137
+ }
138
+
139
+ /*
140
+ * This method may be optimized on some systems (e.g. GNU/Linux) to use
141
+ * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
142
+ * Otherwise this is the same as Kgio::PipeMethods#kgio_write
143
+ */
144
+ static VALUE kgio_send(VALUE io, VALUE str)
145
+ {
146
+ return my_send(io, str, 1);
147
+ }
148
+
149
+ /*
150
+ * This method may be optimized on some systems (e.g. GNU/Linux) to use
151
+ * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
152
+ * Otherwise this is the same as Kgio::PipeMethods#kgio_trywrite
153
+ */
154
+ static VALUE kgio_trysend(VALUE io, VALUE str)
155
+ {
156
+ return my_send(io, str, 0);
157
+ }
158
+ #else /* ! USE_MSG_DONTWAIT */
159
+ # define kgio_send kgio_write
160
+ # define kgio_trysend kgio_trywrite
161
+ #endif /* ! USE_MSG_DONTWAIT */
162
+
163
+ #if defined(KGIO_HAVE_THREAD_CALL_WITHOUT_GVL)
164
+ # include "blocking_io_region.h"
165
+ #ifdef MSG_DONTWAIT /* Linux only */
166
+ # define MY_MSG_DONTWAIT (MSG_DONTWAIT)
167
+ #else
168
+ # define MY_MSG_DONTWAIT (0)
169
+ #endif
170
+
171
+ static VALUE nogvl_send(void *ptr)
172
+ {
173
+ struct wr_args *a = ptr;
174
+
175
+ return (VALUE)send(a->fd, a->ptr, a->len, a->flags);
176
+ }
177
+ /*
178
+ * call-seq:
179
+ *
180
+ * io.kgio_syssend(str, flags) -> nil, String or :wait_writable
181
+ *
182
+ * Returns nil if the write was completed in full.
183
+ *
184
+ * Returns a String containing the unwritten portion if EAGAIN
185
+ * was encountered, but some portion was successfully written.
186
+ *
187
+ * Returns :wait_writable if EAGAIN is encountered and nothing
188
+ * was written.
189
+ *
190
+ * This method is only available on Ruby 1.9.3 or later.
191
+ */
192
+ static VALUE kgio_syssend(VALUE io, VALUE str, VALUE flags)
193
+ {
194
+ struct wr_args a;
195
+ long n;
196
+
197
+ a.flags = NUM2INT(flags);
198
+ prepare_write(&a, io, str);
199
+ if (a.flags & MY_MSG_DONTWAIT) {
200
+ do {
201
+ n = (long)send(a.fd, a.ptr, a.len, a.flags);
202
+ } while (write_check(&a, n, "send", 0) != 0);
203
+ } else {
204
+ do {
205
+ n = (long)rb_thread_io_blocking_region(
206
+ nogvl_send, &a, a.fd);
207
+ } while (write_check(&a, n, "send", 0) != 0);
208
+ }
209
+ return a.buf;
210
+ }
211
+ #endif /* HAVE_RB_THREAD_IO_BLOCKING_REGION */
212
+
213
+ /*
214
+ * call-seq:
215
+ *
216
+ * Kgio.trywrite(io, str) -> nil, String or :wait_writable
217
+ *
218
+ * Returns nil if the write was completed in full.
219
+ *
220
+ * Returns a String containing the unwritten portion if EAGAIN
221
+ * was encountered, but some portion was successfully written.
222
+ *
223
+ * Returns :wait_writable if EAGAIN is encountered and nothing
224
+ * was written.
225
+ *
226
+ * Maybe used in place of PipeMethods#kgio_trywrite for non-Kgio objects
227
+ */
228
+ static VALUE s_trywrite(VALUE mod, VALUE io, VALUE str)
229
+ {
230
+ return my_write(io, str, 0);
231
+ }
232
+
233
+ void init_kgio_write(void)
234
+ {
235
+ VALUE mPipeMethods, mSocketMethods;
236
+ VALUE mKgio = rb_define_module("Kgio");
237
+
238
+ sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
239
+
240
+ rb_define_singleton_method(mKgio, "trywrite", s_trywrite, 2);
241
+
242
+ /*
243
+ * Document-module: Kgio::PipeMethods
244
+ *
245
+ * This module may be used used to create classes that respond to
246
+ * various Kgio methods for reading and writing. This is included
247
+ * in Kgio::Pipe by default.
248
+ */
249
+ mPipeMethods = rb_define_module_under(mKgio, "PipeMethods");
250
+ rb_define_method(mPipeMethods, "kgio_write", kgio_write, 1);
251
+ rb_define_method(mPipeMethods, "kgio_trywrite", kgio_trywrite, 1);
252
+
253
+ /*
254
+ * Document-module: Kgio::SocketMethods
255
+ *
256
+ * This method behaves like Kgio::PipeMethods, but contains
257
+ * optimizations for sockets on certain operating systems
258
+ * (e.g. GNU/Linux).
259
+ */
260
+ mSocketMethods = rb_define_module_under(mKgio, "SocketMethods");
261
+ rb_define_method(mSocketMethods, "kgio_write", kgio_send, 1);
262
+ rb_define_method(mSocketMethods, "kgio_trywrite", kgio_trysend, 1);
263
+
264
+ #ifdef USE_MSG_DONTWAIT
265
+ rb_define_method(mSocketMethods, "kgio_syssend", kgio_syssend, 2);
266
+ #endif
267
+ }