Project

General

Profile

Feature #9323 ยป patch.diff

Glass_saga (Masaki Matsushita), 06/27/2017 05:05 AM

View differences:

include/ruby/intern.h
517 517
RUBY_EXTERN VALUE rb_default_rs;
518 518
RUBY_EXTERN VALUE rb_output_rs;
519 519
VALUE rb_io_write(VALUE, VALUE);
520
VALUE rb_io_writev(VALUE, VALUE);
520 521
VALUE rb_io_gets(VALUE);
521 522
VALUE rb_io_getbyte(VALUE);
522 523
VALUE rb_io_ungetc(VALUE, VALUE);
io.c
162 162
static VALUE argf;
163 163

  
164 164
#define id_exception idException
165
static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
165
static ID id_write, id_writev, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
166 166
static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
167 167
static VALUE sym_textmode, sym_binmode, sym_autoclose;
168 168
static VALUE sym_SET, sym_CUR, sym_END;
......
1533 1533
    return io;
1534 1534
}
1535 1535

  
1536
#ifdef HAVE_WRITEV
1537
struct binwritev_arg {
1538
    rb_io_t *fptr;
1539
    const struct iovec *iov;
1540
    int iovcnt;
1541
};
1542

  
1543
static VALUE
1544
call_writev_internal(VALUE arg)
1545
{
1546
    struct binwritev_arg *p = (struct binwritev_arg *)arg;
1547
    return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
1548
}
1549

  
1550
static long
1551
io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
1552
{
1553
    int i;
1554
    long r, total = 0, written_len = 0;
1555

  
1556
    /* don't write anything if current thread has a pending interrupt. */
1557
    rb_thread_check_ints();
1558

  
1559
    if (iovcnt == 0) return 0;
1560
    for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1561

  
1562
    if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
1563
	fptr->wbuf.off = 0;
1564
	fptr->wbuf.len = 0;
1565
	fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1566
	fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1567
	fptr->write_lock = rb_mutex_new();
1568
	rb_mutex_allow_trap(fptr->write_lock, 1);
1569
    }
1570

  
1571
    if (fptr->wbuf.ptr && fptr->wbuf.len) {
1572
	if (fptr->wbuf.off + fptr->wbuf.len + total <= fptr->wbuf.capa) {
1573
	    long offset = fptr->wbuf.off;
1574
	    for (i = 1; i < iovcnt; i++) {
1575
		memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
1576
		offset += iov[i].iov_len;
1577
	    }
1578
	    fptr->wbuf.len += total;
1579
	    return total;
1580
	}
1581
	else {
1582
	    iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
1583
	    iov[0].iov_len  = fptr->wbuf.len;
1584
	}
1585
    }
1586
    else {
1587
	iov++;
1588
	iovcnt--;
1589
    }
1590

  
1591
  retry:
1592
    if (fptr->write_lock) {
1593
	struct binwritev_arg arg;
1594
	arg.fptr = fptr;
1595
	arg.iov  = iov;
1596
	arg.iovcnt = iovcnt;
1597
	r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
1598
    }
1599
    else {
1600
	r = rb_writev_internal(fptr->fd, iov, iovcnt);
1601
    }
1602

  
1603
    if (r >= 0) {
1604
	written_len += r;
1605
	if (fptr->wbuf.ptr && fptr->wbuf.len) {
1606
	    if (written_len < fptr->wbuf.len) {
1607
		fptr->wbuf.off += r;
1608
		fptr->wbuf.len -= r;
1609
	    }
1610
	    else {
1611
		fptr->wbuf.off = 0;
1612
		fptr->wbuf.len = 0;
1613
	    }
1614
	}
1615
	if (written_len == total) return written_len;
1616

  
1617
	for (i = 0; i < iovcnt; i++) {
1618
	    if (r > (ssize_t)iov[i].iov_len) {
1619
		r -= iov[i].iov_len;
1620
		iov[i].iov_len = 0;
1621
            }
1622
	    else {
1623
		iov[i].iov_base = (char *)iov[i].iov_base + r;
1624
		iov[i].iov_len  -= r;
1625
		break;
1626
	    }
1627
	}
1628

  
1629
        errno = EAGAIN;
1630
    }
1631
    if (rb_io_wait_writable(fptr->fd)) {
1632
        rb_io_check_closed(fptr);
1633
	goto retry;
1634
    }
1635

  
1636
    return -1L;
1637
}
1638

  
1639
static long
1640
io_fwritev(VALUE ary, rb_io_t *fptr)
1641
{
1642
    int i, iovcnt = RARRAY_LENINT(ary) + 1, converted;
1643
    long n;
1644
    VALUE v1, v2, str, tmp, *tmp_array;
1645
    struct iovec *iov;
1646

  
1647
    if (iovcnt > IOV_MAX) {
1648
	rb_raise(rb_eArgError, "too many items (IOV_MAX: %d)", IOV_MAX);
1649
    }
1650

  
1651
    iov = ALLOCV_N(struct iovec, v1, iovcnt);
1652
    tmp_array = ALLOCV_N(VALUE, v2, RARRAY_LEN(ary));
1653

  
1654
    for (i = 0; i < RARRAY_LEN(ary); i++) {
1655
	str = rb_obj_as_string(RARRAY_AREF(ary, i));
1656
	converted = 0;
1657
	str = do_writeconv(str, fptr, &converted);
1658
	if (converted)
1659
	    OBJ_FREEZE(str);
1660

  
1661
	tmp = rb_str_tmp_frozen_acquire(str);
1662
	tmp_array[i] = tmp;
1663
	iov[i+1].iov_base = RSTRING_PTR(tmp);
1664
	iov[i+1].iov_len = RSTRING_LEN(tmp);
1665
    }
1666

  
1667
    n = io_binwritev(iov, iovcnt, fptr);
1668
    if (v1) ALLOCV_END(v1);
1669

  
1670
    for (i = 0; i < RARRAY_LEN(ary); i++) {
1671
	rb_str_tmp_frozen_release(RARRAY_AREF(ary, i), tmp_array[i]);
1672
    }
1673

  
1674
    if (v2) ALLOCV_END(v2);
1675

  
1676
    return n;
1677
}
1678

  
1679
static VALUE
1680
io_writev(VALUE io, VALUE ary)
1681
{
1682
    rb_io_t *fptr;
1683
    long n;
1684
    VALUE tmp;
1685

  
1686
    io = GetWriteIO(io);
1687
    ary = rb_check_array_type(ary);
1688
    tmp = rb_io_check_io(io);
1689
    if (NIL_P(tmp)) {
1690
	/* port is not IO, call writev method for it. */
1691
	return rb_funcallv(io, id_writev, 1, &ary);
1692
    }
1693
    io = tmp;
1694

  
1695
    GetOpenFile(io, fptr);
1696
    rb_io_check_writable(fptr);
1697

  
1698
    n = io_fwritev(ary, fptr);
1699
    if (n == -1L) rb_sys_fail_path(fptr->pathv);
1700

  
1701
    return LONG2FIX(n);
1702
}
1703
#else
1704
static VALUE
1705
io_writev(VALUE io, VALUE ary)
1706
{
1707
    rb_io_t *fptr;
1708
    long n;
1709
    VALUE str, tmp;
1710

  
1711
    io = GetWriteIO(io);
1712
    ary = rb_check_array_type(ary);
1713
    tmp = rb_io_check_io(io);
1714
    if (NIL_P(tmp)) {
1715
	/* port is not IO, call writev method for it. */
1716
	return rb_funcallv(io, id_writev, 1, &ary);
1717
    }
1718
    io = tmp;
1719

  
1720
    str = rb_ary_join(ary, rb_str_new(0, 0));
1721

  
1722
    GetOpenFile(io, fptr);
1723
    rb_io_check_writable(fptr);
1724

  
1725
    n = io_fwrite(str, fptr, 0);
1726
    if (n == -1L) rb_sys_fail_path(fptr->pathv);
1727

  
1728
    return LONG2FIX(n);
1729
}
1730
#endif /* HAVE_WRITEV */
1731

  
1732
VALUE
1733
rb_io_writev(VALUE io, VALUE ary)
1734
{
1735
    return rb_funcallv(io, id_writev, 1, &ary);
1736
}
1737

  
1536 1738
#ifdef HAVE_FSYNC
1537 1739
static VALUE
1538 1740
nogvl_fsync(void *ptr)
......
12503 12705
    rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
12504 12706

  
12505 12707
    id_write = rb_intern("write");
12708
    id_writev = rb_intern("writev");
12506 12709
    id_read = rb_intern("read");
12507 12710
    id_getc = rb_intern("getc");
12508 12711
    id_flush = rb_intern("flush");
......
12636 12839
    rb_define_method(rb_cIO, "readpartial",  io_readpartial, -1);
12637 12840
    rb_define_method(rb_cIO, "read",  io_read, -1);
12638 12841
    rb_define_method(rb_cIO, "write", io_write_m, 1);
12842
    rb_define_method(rb_cIO, "writev", io_writev, 1);
12639 12843
    rb_define_method(rb_cIO, "gets",  rb_io_gets_m, -1);
12640 12844
    rb_define_method(rb_cIO, "readline",  rb_io_readline, -1);
12641 12845
    rb_define_method(rb_cIO, "getc",  rb_io_getc, 0);