kgio 2.8.1 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }