diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-11-24 20:33:19 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-11-24 20:35:17 (GMT) |
commit | 332d60c56dfaa11fdd135088279d15cd5983b3d4 (patch) | |
tree | dd77717a4e1732da929d5ff8a0471fa3f005e201 /3rdParty/Boost/src/boost/asio/detail/impl/descriptor_ops.ipp | |
parent | 90c44a10fec26d2a0935b2d62e82b6a5be028373 (diff) | |
download | swift-contrib-332d60c56dfaa11fdd135088279d15cd5983b3d4.zip swift-contrib-332d60c56dfaa11fdd135088279d15cd5983b3d4.tar.bz2 |
Upgraded Boost to 1.45.0.
Diffstat (limited to '3rdParty/Boost/src/boost/asio/detail/impl/descriptor_ops.ipp')
-rw-r--r-- | 3rdParty/Boost/src/boost/asio/detail/impl/descriptor_ops.ipp | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/asio/detail/impl/descriptor_ops.ipp b/3rdParty/Boost/src/boost/asio/detail/impl/descriptor_ops.ipp new file mode 100644 index 0000000..74a8e6f --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/impl/descriptor_ops.ipp @@ -0,0 +1,372 @@ +// +// detail/impl/descriptor_ops.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP +#define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cerrno> +#include <boost/asio/detail/descriptor_ops.hpp> +#include <boost/asio/error.hpp> + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { +namespace descriptor_ops { + +int open(const char* path, int flags, boost::system::error_code& ec) +{ + errno = 0; + int result = error_wrapper(::open(path, flags), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +} + +int close(int d, state_type& state, boost::system::error_code& ec) +{ + int result = 0; + if (d != -1) + { + if (state & internal_non_blocking) + { +#if defined(__SYMBIAN32__) + int flags = ::fcntl(d, F_GETFL, 0); + if (flags >= 0) + ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK); +#else // defined(__SYMBIAN32__) + ioctl_arg_type arg = 0; + ::ioctl(d, FIONBIO, &arg); +#endif // defined(__SYMBIAN32__) + state &= ~internal_non_blocking; + } + + errno = 0; + result = error_wrapper(::close(d), ec); + } + + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +bool set_internal_non_blocking(int d, + state_type& state, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + + errno = 0; +#if defined(__SYMBIAN32__) + int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec); + if (result >= 0) + { + errno = 0; + result = error_wrapper(::fcntl(d, F_SETFL, result | O_NONBLOCK), ec); + } +#else // defined(__SYMBIAN32__) + ioctl_arg_type arg = 1; + int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec); +#endif // defined(__SYMBIAN32__) + + if (result >= 0) + { + ec = boost::system::error_code(); + state |= internal_non_blocking; + return true; + } + + return false; +} + +std::size_t sync_read(int d, state_type state, buf* bufs, + std::size_t count, bool all_empty, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // A request to read 0 bytes on a stream is a no-op. + if (all_empty) + { + ec = boost::system::error_code(); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + errno = 0; + int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Check for EOF. + if (bytes == 0) + { + ec = boost::asio::error::eof; + return 0; + } + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_read(d, ec) < 0) + return 0; + } +} + +bool non_blocking_read(int d, buf* bufs, std::size_t count, + boost::system::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + errno = 0; + int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec); + + // Check for end of stream. + if (bytes == 0) + { + ec = boost::asio::error::eof; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes > 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +std::size_t sync_write(int d, state_type state, const buf* bufs, + std::size_t count, bool all_empty, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // A request to write 0 bytes on a stream is a no-op. + if (all_empty) + { + ec = boost::system::error_code(); + return 0; + } + + // Write some data. + for (;;) + { + // Try to complete the operation without blocking. + errno = 0; + int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_write(d, ec) < 0) + return 0; + } +} + +bool non_blocking_write(int d, const buf* bufs, std::size_t count, + boost::system::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + errno = 0; + int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec); + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +int ioctl(int d, state_type& state, long cmd, + ioctl_arg_type* arg, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + errno = 0; + int result = error_wrapper(::ioctl(d, cmd, arg), ec); + + if (result >= 0) + { + ec = boost::system::error_code(); + + // When updating the non-blocking mode we always perform the ioctl syscall, + // even if the flags would otherwise indicate that the descriptor is + // already in the correct state. This ensures that the underlying + // descriptor is put into the state that has been requested by the user. If + // the ioctl syscall was successful then we need to update the flags to + // match. + if (cmd == static_cast<long>(FIONBIO)) + { + if (*arg) + { + state |= user_set_non_blocking; + } + else + { + // Clearing the non-blocking mode always overrides any internally-set + // non-blocking flag. Any subsequent asynchronous operations will need + // to re-enable non-blocking I/O. + state &= ~(user_set_non_blocking | internal_non_blocking); + } + } + } + + return result; +} + +int fcntl(int d, long cmd, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + errno = 0; + int result = error_wrapper(::fcntl(d, cmd), ec); + if (result != -1) + ec = boost::system::error_code(); + return result; +} + +int fcntl(int d, long cmd, long arg, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + errno = 0; + int result = error_wrapper(::fcntl(d, cmd, arg), ec); + if (result != -1) + ec = boost::system::error_code(); + return result; +} + +int poll_read(int d, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + pollfd fds; + fds.fd = d; + fds.events = POLLIN; + fds.revents = 0; + errno = 0; + int result = error_wrapper(::poll(&fds, 1, -1), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +} + +int poll_write(int d, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + pollfd fds; + fds.fd = d; + fds.events = POLLOUT; + fds.revents = 0; + errno = 0; + int result = error_wrapper(::poll(&fds, 1, -1), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +} + +} // namespace descriptor_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP |