diff options
Diffstat (limited to 'ACE/ace/OS_NS_sys_uio.cpp')
-rw-r--r-- | ACE/ace/OS_NS_sys_uio.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/ACE/ace/OS_NS_sys_uio.cpp b/ACE/ace/OS_NS_sys_uio.cpp new file mode 100644 index 00000000000..5608d994c1d --- /dev/null +++ b/ACE/ace/OS_NS_sys_uio.cpp @@ -0,0 +1,130 @@ +// $Id$ + +#include "ace/OS_NS_sys_uio.h" + +ACE_RCSID(ace, OS_NS_sys_uio, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "ace/OS_NS_sys_uio.inl" +#endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/OS_Memory.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_unistd.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +# if defined (ACE_LACKS_READV) + +// "Fake" readv for operating systems without it. Note that this is +// thread-safe. + +ssize_t +ACE_OS::readv_emulation (ACE_HANDLE handle, + const iovec *iov, + int n) +{ + ACE_OS_TRACE ("ACE_OS::readv_emulation"); + + // In case there's a single element, skip the memcpy. + if (1 == n) + return ACE_OS::read (handle, iov[0].iov_base, iov[0].iov_len); + + ssize_t length = 0; + int i; + + for (i = 0; i < n; ++i) + if (static_cast<int> (iov[i].iov_len) < 0) + return -1; + else + length += iov[i].iov_len; + + char *buf; +# if defined (ACE_HAS_ALLOCA) + buf = (char *) alloca (length); +# else + ACE_NEW_RETURN (buf, + char[length], + -1); +# endif /* !defined (ACE_HAS_ALLOCA) */ + + length = ACE_OS::read (handle, buf, length); + + if (length != -1) + { + char *ptr = buf; + ssize_t copyn = length; + + for (i = 0; + i < n && copyn > 0; + ++i) + { + ACE_OS::memcpy (iov[i].iov_base, ptr, + // iov_len is int on some platforms, size_t on others + copyn > (int) iov[i].iov_len + ? (size_t) iov[i].iov_len + : (size_t) copyn); + ptr += iov[i].iov_len; + copyn -= iov[i].iov_len; + } + } + +# if !defined (ACE_HAS_ALLOCA) + delete [] buf; +# endif /* !defined (ACE_HAS_ALLOCA) */ + return length; +} +# endif /* ACE_LACKS_READV */ + +# if defined (ACE_LACKS_WRITEV) + +// "Fake" writev for operating systems without it. Note that this is +// thread-safe. + +ssize_t +ACE_OS::writev_emulation (ACE_HANDLE handle, const iovec *iov, int n) +{ + ACE_OS_TRACE ("ACE_OS::writev_emulation"); + + // To avoid having to allocate a temporary buffer to which all of + // the data will be copied and then written, this implementation + // performs incremental writes. + + ssize_t bytes_sent = 0; + + for (int i = 0; i < n; ++i) + { + ssize_t const result = + ACE_OS::write (handle, iov[i].iov_base, iov[i].iov_len); + + if (result == -1) + { + // There is a subtle difference in behaviour depending on + // whether or not any data was sent. If no data was sent, + // then always return -1. Otherwise return bytes_sent. + // This gives the caller an opportunity to keep track of + // bytes that have already been sent. + if (bytes_sent > 0) + break; + else + return -1; + } + else + { + bytes_sent += result; + + // Do not continue on to the next loop iteration if the + // amount of data sent was less than the amount data given. + // This avoids a subtle problem where "holes" in the data + // stream would occur if partial sends of a given buffer in + // the iovec array occured. + if (static_cast<size_t> (result) < iov[i].iov_len) + break; + } + } + + return bytes_sent; +} +# endif /* ACE_LACKS_WRITEV */ + +ACE_END_VERSIONED_NAMESPACE_DECL |