1 /* we do not modify RSTRING pointers here */
5 static VALUE sym_wait_writable
;
16 static void prepare_write(struct wr_args
*a
, VALUE io
, VALUE str
)
18 a
->buf
= (TYPE(str
) == T_STRING
) ? str
: rb_obj_as_string(str
);
19 a
->ptr
= RSTRING_PTR(a
->buf
);
20 a
->len
= RSTRING_LEN(a
->buf
);
22 a
->fd
= my_fileno(io
);
25 static int write_check(struct wr_args
*a
, long n
, const char *msg
, int io_wait
)
32 a
->fd
= my_fileno(a
->io
);
35 if (errno
== EAGAIN
) {
36 long written
= RSTRING_LEN(a
->buf
) - a
->len
;
39 (void)kgio_call_wait_writable(a
->io
);
41 /* buf may be modified in other thread/fiber */
42 a
->len
= RSTRING_LEN(a
->buf
) - written
;
45 a
->ptr
= RSTRING_PTR(a
->buf
) + written
;
47 } else if (written
> 0) {
48 a
->buf
= MY_STR_SUBSEQ(a
->buf
, written
, a
->len
);
50 a
->buf
= sym_wait_writable
;
54 kgio_wr_sys_fail(msg
);
56 assert(n
>= 0 && n
< a
->len
&& "write/send syscall broken?");
64 static VALUE
my_write(VALUE io
, VALUE str
, int io_wait
)
69 prepare_write(&a
, io
, str
);
70 set_nonblocking(a
.fd
);
72 n
= (long)write(a
.fd
, a
.ptr
, a
.len
);
73 if (write_check(&a
, n
, "write", io_wait
) != 0)
75 if (TYPE(a
.buf
) != T_SYMBOL
)
76 kgio_autopush_write(io
);
83 * io.kgio_write(str) -> nil
85 * Returns nil when the write completes.
87 * This may block and call any method defined to +kgio_wait_writable+
90 static VALUE
kgio_write(VALUE io
, VALUE str
)
92 return my_write(io
, str
, 1);
98 * io.kgio_trywrite(str) -> nil, String or :wait_writable
100 * Returns nil if the write was completed in full.
102 * Returns a String containing the unwritten portion if EAGAIN
103 * was encountered, but some portion was successfully written.
105 * Returns :wait_writable if EAGAIN is encountered and nothing
108 static VALUE
kgio_trywrite(VALUE io
, VALUE str
)
110 return my_write(io
, str
, 0);
113 #ifdef USE_MSG_DONTWAIT
115 * This method behaves like Kgio::PipeMethods#kgio_write, except
116 * it will use send(2) with the MSG_DONTWAIT flag on sockets to
117 * avoid unnecessary calls to fcntl(2).
119 static VALUE
my_send(VALUE io
, VALUE str
, int io_wait
)
124 prepare_write(&a
, io
, str
);
126 n
= (long)send(a
.fd
, a
.ptr
, a
.len
, MSG_DONTWAIT
);
127 if (write_check(&a
, n
, "send", io_wait
) != 0)
129 if (TYPE(a
.buf
) != T_SYMBOL
)
130 kgio_autopush_send(io
);
135 * This method may be optimized on some systems (e.g. GNU/Linux) to use
136 * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
137 * Otherwise this is the same as Kgio::PipeMethods#kgio_write
139 static VALUE
kgio_send(VALUE io
, VALUE str
)
141 return my_send(io
, str
, 1);
145 * This method may be optimized on some systems (e.g. GNU/Linux) to use
146 * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
147 * Otherwise this is the same as Kgio::PipeMethods#kgio_trywrite
149 static VALUE
kgio_trysend(VALUE io
, VALUE str
)
151 return my_send(io
, str
, 0);
153 #else /* ! USE_MSG_DONTWAIT */
154 # define kgio_send kgio_write
155 # define kgio_trysend kgio_trywrite
156 #endif /* ! USE_MSG_DONTWAIT */
158 #if defined(KGIO_WITHOUT_GVL)
159 # include "blocking_io_region.h"
160 #ifdef MSG_DONTWAIT /* Linux only */
161 # define MY_MSG_DONTWAIT (MSG_DONTWAIT)
163 # define MY_MSG_DONTWAIT (0)
166 static VALUE
nogvl_send(void *ptr
)
168 struct wr_args
*a
= ptr
;
170 return (VALUE
)send(a
->fd
, a
->ptr
, a
->len
, a
->flags
);
175 * io.kgio_syssend(str, flags) -> nil, String or :wait_writable
177 * Returns nil if the write was completed in full.
179 * Returns a String containing the unwritten portion if EAGAIN
180 * was encountered, but some portion was successfully written.
182 * Returns :wait_writable if EAGAIN is encountered and nothing
185 * This method is only available on Ruby 1.9.3 or later.
187 static VALUE
kgio_syssend(VALUE io
, VALUE str
, VALUE flags
)
192 a
.flags
= NUM2INT(flags
);
193 prepare_write(&a
, io
, str
);
194 if (a
.flags
& MY_MSG_DONTWAIT
) {
196 n
= (long)send(a
.fd
, a
.ptr
, a
.len
, a
.flags
);
197 } while (write_check(&a
, n
, "send", 0) != 0);
200 n
= (long)rb_thread_io_blocking_region(
201 nogvl_send
, &a
, a
.fd
);
202 } while (write_check(&a
, n
, "send", 0) != 0);
206 #endif /* HAVE_RB_THREAD_IO_BLOCKING_REGION */
211 * Kgio.trywrite(io, str) -> nil, String or :wait_writable
213 * Returns nil if the write was completed in full.
215 * Returns a String containing the unwritten portion if EAGAIN
216 * was encountered, but some portion was successfully written.
218 * Returns :wait_writable if EAGAIN is encountered and nothing
221 * Maybe used in place of PipeMethods#kgio_trywrite for non-Kgio objects
223 static VALUE
s_trywrite(VALUE mod
, VALUE io
, VALUE str
)
225 return my_write(io
, str
, 0);
228 void init_kgio_write(void)
230 VALUE mPipeMethods
, mSocketMethods
;
231 VALUE mKgio
= rb_define_module("Kgio");
233 sym_wait_writable
= ID2SYM(rb_intern("wait_writable"));
235 rb_define_singleton_method(mKgio
, "trywrite", s_trywrite
, 2);
238 * Document-module: Kgio::PipeMethods
240 * This module may be used used to create classes that respond to
241 * various Kgio methods for reading and writing. This is included
242 * in Kgio::Pipe by default.
244 mPipeMethods
= rb_define_module_under(mKgio
, "PipeMethods");
245 rb_define_method(mPipeMethods
, "kgio_write", kgio_write
, 1);
246 rb_define_method(mPipeMethods
, "kgio_trywrite", kgio_trywrite
, 1);
249 * Document-module: Kgio::SocketMethods
251 * This method behaves like Kgio::PipeMethods, but contains
252 * optimizations for sockets on certain operating systems
255 mSocketMethods
= rb_define_module_under(mKgio
, "SocketMethods");
256 rb_define_method(mSocketMethods
, "kgio_write", kgio_send
, 1);
257 rb_define_method(mSocketMethods
, "kgio_trywrite", kgio_trysend
, 1);
259 #if defined(KGIO_WITHOUT_GVL)
260 rb_define_method(mSocketMethods
, "kgio_syssend", kgio_syssend
, 2);