Commit bda243ec by Paolo Carlini Committed by Paolo Carlini

Nathan C.

2003-07-14  Paolo Carlini  <pcarlini@unitus.it>
	    Nathan C. Myers  <ncm-nospam@cantrip.org>

	PR libstdc++/11378
	* include/std/std_fstream.h (xsputn): Declare only.
	* include/bits/fstream.tcc (xsputn): Define, optimize for the
	always_noconv() case: when __n is sufficiently large flush
	the buffer and issue a direct write, if possible combining the
	two with writev in __basic_file<>::xsputn_2.
	* config/io/basic_file_stdio.h (__basic_file<>::xsputn_2):
	New, declare.
	* config/io/basic_file_stdio.cc (__basic_file<>::xsputn_2):
	Define.
	* acinclude.m4 (GLIBCXX_CHECK_WRITE): New macro, checking for
	the availability of writev in <sys/uio.h>.
	* configure.in: Call here.
	* acconfig.h: Add undef for the corresponding symbol.
	* aclocal.m4: Regenerate.
	* configure: Regenerate.
	* config.h.in: Regenerate.
	* testsuite/27_io/basic_filebuf/setbuf/char/3.cc: Tweak.

	* include/std/std_fstream.h (sync): Constify a variable.

Co-Authored-By: Nathan C. Myers <ncm-nospam@cantrip.org>

From-SVN: r69341
parent 19948e32
2003-07-14 Paolo Carlini <pcarlini@unitus.it>
Nathan C. Myers <ncm-nospam@cantrip.org>
PR libstdc++/11378
* include/std/std_fstream.h (xsputn): Declare only.
* include/bits/fstream.tcc (xsputn): Define, optimize for the
always_noconv() case: when __n is sufficiently large flush
the buffer and issue a direct write, if possible combining the
two with writev in __basic_file<>::xsputn_2.
* config/io/basic_file_stdio.h (__basic_file<>::xsputn_2):
New, declare.
* config/io/basic_file_stdio.cc (__basic_file<>::xsputn_2):
Define.
* acinclude.m4 (GLIBCXX_CHECK_WRITE): New macro, checking for
the availability of writev in <sys/uio.h>.
* configure.in: Call here.
* acconfig.h: Add undef for the corresponding symbol.
* aclocal.m4: Regenerate.
* configure: Regenerate.
* config.h.in: Regenerate.
* testsuite/27_io/basic_filebuf/setbuf/char/3.cc: Tweak.
* include/std/std_fstream.h (sync): Constify a variable.
2003-07-14 Benjamin Kosnik <bkoz@redhat.com> 2003-07-14 Benjamin Kosnik <bkoz@redhat.com>
* testsuite/27_io/ios_base/cons/assign_neg.cc: Fix line numbers. * testsuite/27_io/ios_base/cons/assign_neg.cc: Fix line numbers.
......
...@@ -144,6 +144,9 @@ ...@@ -144,6 +144,9 @@
// Define if S_IFREG is available in <sys/stat.h>. // Define if S_IFREG is available in <sys/stat.h>.
#undef HAVE_S_IFREG #undef HAVE_S_IFREG
// Define if writev is available in <sys/uio.h>.
#undef HAVE_WRITEV
// Define if LC_MESSAGES is available in <locale.h>. // Define if LC_MESSAGES is available in <locale.h>.
#undef HAVE_LC_MESSAGES #undef HAVE_LC_MESSAGES
......
...@@ -2162,6 +2162,23 @@ AC_DEFUN(GLIBCXX_CHECK_POLL, [ ...@@ -2162,6 +2162,23 @@ AC_DEFUN(GLIBCXX_CHECK_POLL, [
fi fi
]) ])
dnl
dnl Check whether writev is available in <sys/uio.h>.
dnl
AC_DEFUN(GLIBCXX_CHECK_WRITEV, [
AC_CACHE_VAL(glibcxx_cv_WRITEV, [
AC_TRY_COMPILE([#include <sys/uio.h>],
[struct iovec iov[2]; writev(0, iov, 0); ],
[glibcxx_cv_WRITEV=yes],
[glibcxx_cv_WRITEV=no])
])
if test x$glibcxx_cv_WRITEV = xyes; then
AC_DEFINE(HAVE_WRITEV)
fi
])
# Check whether LC_MESSAGES is available in <locale.h>. # Check whether LC_MESSAGES is available in <locale.h>.
# Ulrich Drepper <drepper@cygnus.com>, 1995. # Ulrich Drepper <drepper@cygnus.com>, 1995.
# #
......
...@@ -2174,6 +2174,23 @@ AC_DEFUN(GLIBCXX_CHECK_POLL, [ ...@@ -2174,6 +2174,23 @@ AC_DEFUN(GLIBCXX_CHECK_POLL, [
fi fi
]) ])
dnl
dnl Check whether writev is available in <sys/uio.h>.
dnl
AC_DEFUN(GLIBCXX_CHECK_WRITEV, [
AC_CACHE_VAL(glibcxx_cv_WRITEV, [
AC_TRY_COMPILE([#include <sys/uio.h>],
[struct iovec iov[2]; writev(0, iov, 0); ],
[glibcxx_cv_WRITEV=yes],
[glibcxx_cv_WRITEV=no])
])
if test x$glibcxx_cv_WRITEV = xyes; then
AC_DEFINE(HAVE_WRITEV)
fi
])
# Check whether LC_MESSAGES is available in <locale.h>. # Check whether LC_MESSAGES is available in <locale.h>.
# Ulrich Drepper <drepper@cygnus.com>, 1995. # Ulrich Drepper <drepper@cygnus.com>, 1995.
# #
......
...@@ -122,6 +122,9 @@ ...@@ -122,6 +122,9 @@
// Define if S_IFREG is available in <sys/stat.h>. // Define if S_IFREG is available in <sys/stat.h>.
#undef HAVE_S_IFREG #undef HAVE_S_IFREG
// Define if writev is available in <sys/uio.h>.
#undef HAVE_WRITEV
// Define if LC_MESSAGES is available in <locale.h>. // Define if LC_MESSAGES is available in <locale.h>.
#undef HAVE_LC_MESSAGES #undef HAVE_LC_MESSAGES
...@@ -749,9 +752,6 @@ ...@@ -749,9 +752,6 @@
/* Define if you have the <nan.h> header file. */ /* Define if you have the <nan.h> header file. */
#undef HAVE_NAN_H #undef HAVE_NAN_H
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <sys/filio.h> header file. */ /* Define if you have the <sys/filio.h> header file. */
#undef HAVE_SYS_FILIO_H #undef HAVE_SYS_FILIO_H
...@@ -776,6 +776,9 @@ ...@@ -776,6 +776,9 @@
/* Define if you have the <sys/types.h> header file. */ /* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H #undef HAVE_SYS_TYPES_H
/* Define if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define if you have the <unistd.h> header file. */ /* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H
......
...@@ -50,6 +50,10 @@ ...@@ -50,6 +50,10 @@
#include <poll.h> #include <poll.h>
#endif #endif
#ifdef _GLIBCXX_HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG) #if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG)
# include <sys/stat.h> # include <sys/stat.h>
# ifdef _GLIBCXX_HAVE_S_ISREG # ifdef _GLIBCXX_HAVE_S_ISREG
...@@ -225,6 +229,40 @@ namespace std ...@@ -225,6 +229,40 @@ namespace std
return __ret; return __ret;
} }
streamsize
__basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
const char* __s2, streamsize __n2)
{
streamsize __ret = 0;
#ifdef _GLIBCXX_HAVE_WRITEV
struct iovec __iov[2];
__iov[0].iov_base = const_cast<char*>(__s1);
__iov[0].iov_len = __n1;
__iov[1].iov_base = const_cast<char*>(__s2);
__iov[1].iov_len = __n2;
do
__ret = writev(this->fd(), __iov, 2);
while (__ret == -1L && errno == EINTR);
#else
if (__n1)
do
__ret = write(this->fd(), __s1, __n1);
while (__ret == -1L && errno == EINTR);
if (__ret == __n1)
{
do
__ret = write(this->fd(), __s2, __n2);
while (__ret == -1L && errno == EINTR);
if (__ret != -1L)
__ret += __n1;
}
#endif
return __ret;
}
streampos streampos
__basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way, __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way,
ios_base::openmode /*__mode*/) ios_base::openmode /*__mode*/)
......
...@@ -97,6 +97,10 @@ namespace std ...@@ -97,6 +97,10 @@ namespace std
xsputn(const char* __s, streamsize __n); xsputn(const char* __s, streamsize __n);
streamsize streamsize
xsputn_2(const char* __s1, streamsize __n1,
const char* __s2, streamsize __n2);
streamsize
xsgetn(char* __s, streamsize __n); xsgetn(char* __s, streamsize __n);
streampos streampos
......
...@@ -423,6 +423,10 @@ else ...@@ -423,6 +423,10 @@ else
GLIBCXX_CHECK_POLL GLIBCXX_CHECK_POLL
GLIBCXX_CHECK_S_ISREG_OR_S_IFREG GLIBCXX_CHECK_S_ISREG_OR_S_IFREG
# For xsputn_2().
AC_CHECK_HEADERS(sys/uio.h)
GLIBCXX_CHECK_WRITEV
AC_LC_MESSAGES AC_LC_MESSAGES
AC_TRY_COMPILE([ AC_TRY_COMPILE([
......
...@@ -438,6 +438,54 @@ namespace std ...@@ -438,6 +438,54 @@ namespace std
return __elen && __elen == __plen; return __elen && __elen == __plen;
} }
template<typename _CharT, typename _Traits>
streamsize
basic_filebuf<_CharT, _Traits>::
xsputn(const _CharT* __s, streamsize __n)
{
streamsize __ret = 0;
// Optimization in the always_noconv() case, to be generalized in the
// future: when __n is sufficiently large we write directly instead of
// using the buffer.
const bool __testout = this->_M_mode & ios_base::out;
if (__testout && !_M_reading
&& __check_facet(_M_codecvt).always_noconv())
{
// Measurement would reveal the best choice.
const streamsize __chunk = 1ul << 10;
streamsize __bufavail = this->epptr() - this->pptr();
// Don't mistake 'uncommitted' mode buffered with unbuffered.
if (!_M_writing && this->_M_buf_size > 1)
__bufavail = this->_M_buf_size - 1;
const streamsize __limit = std::min(__chunk, __bufavail);
if (__n >= __limit)
{
const streamsize __buffill = this->pptr() - this->pbase();
const char* __buf = reinterpret_cast<const char*>(this->pbase());
__ret = _M_file.xsputn_2(__buf, __buffill,
reinterpret_cast<const char*>(__s), __n);
if (__ret == __buffill + __n)
{
_M_set_buffer(0);
_M_writing = true;
}
if (__ret > __buffill)
__ret -= __buffill;
else
__ret = 0;
}
else
__ret = __streambuf_type::xsputn(__s, __n);
}
else
__ret = __streambuf_type::xsputn(__s, __n);
return __ret;
}
template<typename _CharT, typename _Traits> template<typename _CharT, typename _Traits>
typename basic_filebuf<_CharT, _Traits>::__streambuf_type* typename basic_filebuf<_CharT, _Traits>::__streambuf_type*
basic_filebuf<_CharT, _Traits>:: basic_filebuf<_CharT, _Traits>::
......
...@@ -365,7 +365,7 @@ namespace std ...@@ -365,7 +365,7 @@ namespace std
// NB: _M_file.sync() will be called within. // NB: _M_file.sync() will be called within.
if (this->pbase() < this->pptr()) if (this->pbase() < this->pptr())
{ {
int_type __tmp = this->overflow(); const int_type __tmp = this->overflow();
if (traits_type::eq_int_type(__tmp, traits_type::eof())) if (traits_type::eq_int_type(__tmp, traits_type::eof()))
__ret = -1; __ret = -1;
else else
...@@ -407,8 +407,7 @@ namespace std ...@@ -407,8 +407,7 @@ namespace std
// [documentation is inherited] // [documentation is inherited]
virtual streamsize virtual streamsize
xsputn(const char_type* __s, streamsize __n) xsputn(const char_type* __s, streamsize __n);
{ return __streambuf_type::xsputn(__s, __n); }
/** /**
* @if maint * @if maint
......
...@@ -34,7 +34,9 @@ void test02() ...@@ -34,7 +34,9 @@ void test02()
filebuf fbuf01; filebuf fbuf01;
fbuf01.open("tmp", ios_base::out); fbuf01.open("tmp", ios_base::out);
fbuf01.pubsetbuf(buf, strlitsize); // NB: +2 otherwise sputn is optimized to a direct write,
// bypassing the buffer.
fbuf01.pubsetbuf(buf, strlitsize + 2);
fbuf01.sputn(strlit, strlitsize); fbuf01.sputn(strlit, strlitsize);
VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 ); VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment