1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Move IO write buffer allocation into function.

This commit is contained in:
Samuel Williams 2022-01-09 00:03:16 +13:00 committed by GitHub
parent 47a05f7c09
commit 0ca00e2cb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2022-01-08 20:03:46 +09:00
Merged: https://github.com/ruby/ruby/pull/5418

Merged-By: ioquatix <samuel@codeotaku.com>

218
io.c
View file

@ -1646,6 +1646,19 @@ io_binwrite_string(VALUE arg)
}
#endif
inline static void
io_allocate_write_buffer(rb_io_t *fptr, int sync)
{
if (fptr->wbuf.ptr == NULL && !(sync && (fptr->mode & FMODE_SYNC))) {
fptr->wbuf.off = 0;
fptr->wbuf.len = 0;
fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
fptr->write_lock = rb_mutex_new();
rb_mutex_allow_trap(fptr->write_lock, 1);
}
}
static long
io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
{
@ -1656,14 +1669,7 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
if ((n = len) <= 0) return n;
if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
fptr->wbuf.off = 0;
fptr->wbuf.len = 0;
fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
fptr->write_lock = rb_mutex_new();
rb_mutex_allow_trap(fptr->write_lock, 1);
}
io_allocate_write_buffer(fptr, !nosync);
if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
(fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
@ -1865,78 +1871,79 @@ io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
if (iovcnt == 0) return 0;
for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
fptr->wbuf.off = 0;
fptr->wbuf.len = 0;
fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
fptr->write_lock = rb_mutex_new();
rb_mutex_allow_trap(fptr->write_lock, 1);
}
io_allocate_write_buffer(fptr, 1);
if (fptr->wbuf.ptr && fptr->wbuf.len) {
long offset = fptr->wbuf.off + fptr->wbuf.len;
if (offset + total <= fptr->wbuf.capa) {
for (i = 1; i < iovcnt; i++) {
memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
offset += iov[i].iov_len;
}
fptr->wbuf.len += total;
return total;
}
else {
iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
iov[0].iov_len = fptr->wbuf.len;
}
long offset = fptr->wbuf.off + fptr->wbuf.len;
if (offset + total <= fptr->wbuf.capa) {
for (i = 1; i < iovcnt; i++) {
memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
offset += iov[i].iov_len;
}
fptr->wbuf.len += total;
return total;
}
else {
iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
iov[0].iov_len = fptr->wbuf.len;
}
}
else {
iov++;
if (!--iovcnt) return 0;
iov++;
if (!--iovcnt) return 0;
}
retry:
if (fptr->write_lock) {
struct binwritev_arg arg;
arg.fptr = fptr;
arg.iov = iov;
arg.iovcnt = iovcnt;
r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
struct binwritev_arg arg;
arg.fptr = fptr;
arg.iov = iov;
arg.iovcnt = iovcnt;
r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
}
else {
r = rb_writev_internal(fptr, iov, iovcnt);
r = rb_writev_internal(fptr, iov, iovcnt);
}
if (r >= 0) {
written_len += r;
if (fptr->wbuf.ptr && fptr->wbuf.len) {
if (written_len < fptr->wbuf.len) {
fptr->wbuf.off += r;
fptr->wbuf.len -= r;
}
else {
written_len -= fptr->wbuf.len;
fptr->wbuf.off = 0;
fptr->wbuf.len = 0;
}
}
if (written_len == total) return total;
written_len += r;
if (fptr->wbuf.ptr && fptr->wbuf.len) {
if (written_len < fptr->wbuf.len) {
fptr->wbuf.off += r;
fptr->wbuf.len -= r;
}
else {
written_len -= fptr->wbuf.len;
fptr->wbuf.off = 0;
fptr->wbuf.len = 0;
}
}
while (r >= (ssize_t)iov->iov_len) {
/* iovcnt > 0 */
r -= iov->iov_len;
iov->iov_len = 0;
iov++;
if (!--iovcnt) return total;
/* defensive check: written_len should == total */
}
iov->iov_base = (char *)iov->iov_base + r;
iov->iov_len -= r;
if (written_len == total) return total;
errno = EAGAIN;
while (r >= (ssize_t)iov->iov_len) {
/* iovcnt > 0 */
r -= iov->iov_len;
iov->iov_len = 0;
iov++;
if (!--iovcnt) {
// assert(written_len == total);
return total;
}
}
iov->iov_base = (char *)iov->iov_base + r;
iov->iov_len -= r;
errno = EAGAIN;
}
if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
rb_io_check_closed(fptr);
goto retry;
rb_io_check_closed(fptr);
goto retry;
}
return -1L;
@ -1954,24 +1961,26 @@ io_fwritev(int argc, const VALUE *argv, rb_io_t *fptr)
tmp_array = ALLOCV_N(VALUE, v2, argc);
for (i = 0; i < argc; i++) {
str = rb_obj_as_string(argv[i]);
converted = 0;
str = do_writeconv(str, fptr, &converted);
if (converted)
OBJ_FREEZE(str);
str = rb_obj_as_string(argv[i]);
converted = 0;
str = do_writeconv(str, fptr, &converted);
tmp = rb_str_tmp_frozen_acquire(str);
tmp_array[i] = tmp;
/* iov[0] is reserved for buffer of fptr */
iov[i+1].iov_base = RSTRING_PTR(tmp);
iov[i+1].iov_len = RSTRING_LEN(tmp);
if (converted)
OBJ_FREEZE(str);
tmp = rb_str_tmp_frozen_acquire(str);
tmp_array[i] = tmp;
/* iov[0] is reserved for buffer of fptr */
iov[i+1].iov_base = RSTRING_PTR(tmp);
iov[i+1].iov_len = RSTRING_LEN(tmp);
}
n = io_binwritev(iov, iovcnt, fptr);
if (v1) ALLOCV_END(v1);
for (i = 0; i < argc; i++) {
rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
}
if (v2) ALLOCV_END(v2);
@ -2000,10 +2009,12 @@ io_writev(int argc, const VALUE *argv, VALUE io)
io = GetWriteIO(io);
tmp = rb_io_check_io(io);
if (NIL_P(tmp)) {
/* port is not IO, call write method for it. */
return rb_funcallv(io, id_write, argc, argv);
/* port is not IO, call write method for it. */
return rb_funcallv(io, id_write, argc, argv);
}
io = tmp;
GetOpenFile(io, fptr);
@ -2011,18 +2022,21 @@ io_writev(int argc, const VALUE *argv, VALUE io)
for (i = 0; i < argc; i += cnt) {
#ifdef HAVE_WRITEV
if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
n = io_fwritev(cnt, &argv[i], fptr);
}
else
if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
n = io_fwritev(cnt, &argv[i], fptr);
}
else
#endif
{
cnt = 1;
/* sync at last item */
n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
}
if (n < 0L) rb_sys_fail_on_write(fptr);
total = rb_fix_plus(LONG2FIX(n), total);
{
cnt = 1;
/* sync at last item */
n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
}
if (n < 0L)
rb_sys_fail_on_write(fptr);
total = rb_fix_plus(LONG2FIX(n), total);
}
return total;
@ -2051,11 +2065,11 @@ static VALUE
io_write_m(int argc, VALUE *argv, VALUE io)
{
if (argc != 1) {
return io_writev(argc, argv, io);
return io_writev(argc, argv, io);
}
else {
VALUE str = argv[0];
return io_write(io, str, 0);
VALUE str = argv[0];
return io_write(io, str, 0);
}
}
@ -2069,16 +2083,22 @@ static VALUE
rb_io_writev(VALUE io, int argc, const VALUE *argv)
{
if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
VALUE klass = CLASS_OF(io);
char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
" which accepts just one argument",
klass, sep);
}
do rb_io_write(io, *argv++); while (--argc);
return argv[0]; /* unused right now */
if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
VALUE klass = CLASS_OF(io);
char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
rb_category_warning(
RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
" which accepts just one argument",
klass, sep
);
}
do rb_io_write(io, *argv++); while (--argc);
/* unused right now */
return argv[0];
}
return rb_funcallv(io, id_write, argc, argv);
}