asio sync
This commit is contained in:
parent
8a833af738
commit
ffa2066046
|
@ -1,74 +0,0 @@
|
|||
//
|
||||
// asio.hpp
|
||||
// ~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2007 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 ASIO_HPP
|
||||
#define ASIO_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/basic_datagram_socket.hpp"
|
||||
#include "asio/basic_deadline_timer.hpp"
|
||||
#include "asio/basic_io_object.hpp"
|
||||
#include "asio/basic_socket_acceptor.hpp"
|
||||
#include "asio/basic_socket_iostream.hpp"
|
||||
#include "asio/basic_socket_streambuf.hpp"
|
||||
#include "asio/basic_stream_socket.hpp"
|
||||
#include "asio/basic_streambuf.hpp"
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/buffered_read_stream_fwd.hpp"
|
||||
#include "asio/buffered_read_stream.hpp"
|
||||
#include "asio/buffered_stream_fwd.hpp"
|
||||
#include "asio/buffered_stream.hpp"
|
||||
#include "asio/buffered_write_stream_fwd.hpp"
|
||||
#include "asio/buffered_write_stream.hpp"
|
||||
#include "asio/completion_condition.hpp"
|
||||
#include "asio/datagram_socket_service.hpp"
|
||||
#include "asio/deadline_timer_service.hpp"
|
||||
#include "asio/deadline_timer.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/error_code.hpp"
|
||||
#include "asio/handler_alloc_hook.hpp"
|
||||
#include "asio/handler_invoke_hook.hpp"
|
||||
#include "asio/io_service.hpp"
|
||||
#include "asio/ip/address.hpp"
|
||||
#include "asio/ip/address_v4.hpp"
|
||||
#include "asio/ip/address_v6.hpp"
|
||||
#include "asio/ip/basic_endpoint.hpp"
|
||||
#include "asio/ip/basic_resolver.hpp"
|
||||
#include "asio/ip/basic_resolver_entry.hpp"
|
||||
#include "asio/ip/basic_resolver_iterator.hpp"
|
||||
#include "asio/ip/basic_resolver_query.hpp"
|
||||
#include "asio/ip/host_name.hpp"
|
||||
#include "asio/ip/multicast.hpp"
|
||||
#include "asio/ip/resolver_query_base.hpp"
|
||||
#include "asio/ip/resolver_service.hpp"
|
||||
#include "asio/ip/tcp.hpp"
|
||||
#include "asio/ip/udp.hpp"
|
||||
#include "asio/ip/unicast.hpp"
|
||||
#include "asio/ip/v6_only.hpp"
|
||||
#include "asio/is_read_buffered.hpp"
|
||||
#include "asio/is_write_buffered.hpp"
|
||||
#include "asio/placeholders.hpp"
|
||||
#include "asio/read.hpp"
|
||||
#include "asio/read_until.hpp"
|
||||
#include "asio/socket_acceptor_service.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
#include "asio/strand.hpp"
|
||||
#include "asio/stream_socket_service.hpp"
|
||||
#include "asio/streambuf.hpp"
|
||||
#include "asio/system_error.hpp"
|
||||
#include "asio/thread.hpp"
|
||||
#include "asio/time_traits.hpp"
|
||||
#include "asio/version.hpp"
|
||||
#include "asio/write.hpp"
|
||||
|
||||
#endif // ASIO_HPP
|
|
@ -0,0 +1,4 @@
|
|||
Copyright (c) 2003-2007 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)
|
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -732,8 +732,8 @@ public:
|
|||
* completes. Copies will be made of the handler as required. The function
|
||||
* signature of the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::system_error& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
|
|
|
@ -34,7 +34,8 @@ public:
|
|||
/// The underlying implementation type of I/O object.
|
||||
typedef typename service_type::implementation_type implementation_type;
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
/**
|
||||
* This function may be used to obtain the io_service object that the I/O
|
||||
* object uses to dispatch handlers for asynchronous operations.
|
||||
|
@ -44,7 +45,20 @@ public:
|
|||
*/
|
||||
asio::io_service& io_service()
|
||||
{
|
||||
return service.io_service();
|
||||
return service.get_io_service();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
/**
|
||||
* This function may be used to obtain the io_service object that the I/O
|
||||
* object uses to dispatch handlers for asynchronous operations.
|
||||
*
|
||||
* @return A reference to the io_service object that the I/O object will use
|
||||
* to dispatch handlers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return service.get_io_service();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
//
|
||||
// basic_resolver.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 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 ASIO_BASIC_RESOLVER_HPP
|
||||
#define ASIO_BASIC_RESOLVER_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/basic_io_object.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/error_handler.hpp"
|
||||
#include "asio/resolver_service.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Provides endpoint resolution functionality.
|
||||
/**
|
||||
* The basic_resolver class template provides the ability to resolve a query
|
||||
* to a list of endpoints.
|
||||
*
|
||||
* @par Thread Safety:
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*
|
||||
* @par Concepts:
|
||||
* Async_Object, Error_Source.
|
||||
*/
|
||||
template <typename Protocol, typename Service = resolver_service<Protocol> >
|
||||
class basic_resolver
|
||||
: public basic_io_object<Service>
|
||||
{
|
||||
public:
|
||||
/// The protocol type.
|
||||
typedef Protocol protocol_type;
|
||||
|
||||
/// The endpoint type.
|
||||
typedef typename Protocol::endpoint endpoint_type;
|
||||
|
||||
/// The query type.
|
||||
typedef typename Protocol::resolver_query query;
|
||||
|
||||
/// The iterator type.
|
||||
typedef typename Protocol::resolver_iterator iterator;
|
||||
|
||||
/// The type used for reporting errors.
|
||||
typedef asio::error error_type;
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* This constructor creates a basic_resolver.
|
||||
*
|
||||
* @param io_service The io_service object that the resolver will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||
*/
|
||||
explicit basic_resolver(asio::io_service& io_service)
|
||||
: basic_io_object<Service>(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
/// Cancel any asynchronous operations that are waiting on the resolver.
|
||||
/**
|
||||
* This function forces the completion of any pending asynchronous
|
||||
* operations on the host resolver. The handler for each cancelled operation
|
||||
* will be invoked with the asio::error::operation_aborted error code.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
return this->service.cancel(this->implementation);
|
||||
}
|
||||
|
||||
/// Resolve a query to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve a query into a list of endpoint entries.
|
||||
*
|
||||
* @param q A query object that determines what endpoints will be returned.
|
||||
*
|
||||
* @returns A forward-only iterator that can be used to traverse the list
|
||||
* of endpoint entries.
|
||||
*
|
||||
* @throws asio::error Thrown on failure.
|
||||
*
|
||||
* @note A default constructed iterator represents the end of the list.
|
||||
*
|
||||
* @note A successful call to this function is guaranteed to return at least
|
||||
* one entry.
|
||||
*/
|
||||
iterator resolve(const query& q)
|
||||
{
|
||||
return this->service.resolve(this->implementation, q, throw_error());
|
||||
}
|
||||
|
||||
/// Resolve a query to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve a query into a list of endpoint entries.
|
||||
*
|
||||
* @param q A query object that determines what endpoints will be returned.
|
||||
*
|
||||
* @returns A forward-only iterator that can be used to traverse the list
|
||||
* of endpoint entries. Returns a default constructed iterator if an error
|
||||
* occurs.
|
||||
*
|
||||
* @param error_handler A handler to be called when the operation completes,
|
||||
* to indicate whether or not an error has occurred. Copies will be made of
|
||||
* the handler as required. The function signature of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::error& error // Result of operation.
|
||||
* ); @endcode
|
||||
*
|
||||
* @note A default constructed iterator represents the end of the list.
|
||||
*
|
||||
* @note A successful call to this function is guaranteed to return at least
|
||||
* one entry.
|
||||
*/
|
||||
template <typename Error_Handler>
|
||||
iterator resolve(const query& q, Error_Handler error_handler)
|
||||
{
|
||||
return this->service.resolve(this->implementation, q, error_handler);
|
||||
}
|
||||
|
||||
/// Asynchronously resolve a query to a list of entries.
|
||||
/**
|
||||
* This function is used to asynchronously resolve a query into a list of
|
||||
* endpoint entries.
|
||||
*
|
||||
* @param q A query object that determines what endpoints will be returned.
|
||||
*
|
||||
* @param handler The handler to be called when the resolve operation
|
||||
* completes. Copies will be made of the handler as required. The function
|
||||
* signature of the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error& error, // Result of operation.
|
||||
* resolver::iterator iterator // Forward-only iterator that can be used to
|
||||
* // traverse the list of endpoint entries.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_service::post().
|
||||
*
|
||||
* @note A default constructed iterator represents the end of the list.
|
||||
*
|
||||
* @note A successful resolve operation is guaranteed to pass at least one
|
||||
* entry to the handler.
|
||||
*/
|
||||
template <typename Handler>
|
||||
void async_resolve(const query& q, Handler handler)
|
||||
{
|
||||
return this->service.async_resolve(this->implementation, q, handler);
|
||||
}
|
||||
|
||||
/// Resolve an endpoint to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve an endpoint into a list of endpoint
|
||||
* entries.
|
||||
*
|
||||
* @param e An endpoint object that determines what endpoints will be
|
||||
* returned.
|
||||
*
|
||||
* @returns A forward-only iterator that can be used to traverse the list
|
||||
* of endpoint entries.
|
||||
*
|
||||
* @throws asio::error Thrown on failure.
|
||||
*
|
||||
* @note A default constructed iterator represents the end of the list.
|
||||
*
|
||||
* @note A successful call to this function is guaranteed to return at least
|
||||
* one entry.
|
||||
*/
|
||||
iterator resolve(const endpoint_type& e)
|
||||
{
|
||||
return this->service.resolve(this->implementation, e, throw_error());
|
||||
}
|
||||
|
||||
/// Resolve an endpoint to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve an endpoint into a list of endpoint
|
||||
* entries.
|
||||
*
|
||||
* @param e An endpoint object that determines what endpoints will be
|
||||
* returned.
|
||||
*
|
||||
* @returns A forward-only iterator that can be used to traverse the list
|
||||
* of endpoint entries. Returns a default constructed iterator if an error
|
||||
* occurs.
|
||||
*
|
||||
* @param error_handler A handler to be called when the operation completes,
|
||||
* to indicate whether or not an error has occurred. Copies will be made of
|
||||
* the handler as required. The function signature of the handler must be:
|
||||
* @code void error_handler(
|
||||
* const asio::error& error // Result of operation.
|
||||
* ); @endcode
|
||||
*
|
||||
* @note A default constructed iterator represents the end of the list.
|
||||
*
|
||||
* @note A successful call to this function is guaranteed to return at least
|
||||
* one entry.
|
||||
*/
|
||||
template <typename Error_Handler>
|
||||
iterator resolve(const endpoint_type& e, Error_Handler error_handler)
|
||||
{
|
||||
return this->service.resolve(this->implementation, e, error_handler);
|
||||
}
|
||||
|
||||
/// Asynchronously resolve an endpoint to a list of entries.
|
||||
/**
|
||||
* This function is used to asynchronously resolve an endpoint into a list of
|
||||
* endpoint entries.
|
||||
*
|
||||
* @param e An endpoint object that determines what endpoints will be
|
||||
* returned.
|
||||
*
|
||||
* @param handler The handler to be called when the resolve operation
|
||||
* completes. Copies will be made of the handler as required. The function
|
||||
* signature of the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error& error, // Result of operation.
|
||||
* resolver::iterator iterator // Forward-only iterator that can be used to
|
||||
* // traverse the list of endpoint entries.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_service::post().
|
||||
*
|
||||
* @note A default constructed iterator represents the end of the list.
|
||||
*
|
||||
* @note A successful resolve operation is guaranteed to pass at least one
|
||||
* entry to the handler.
|
||||
*/
|
||||
template <typename Handler>
|
||||
void async_resolve(const endpoint_type& e, Handler handler)
|
||||
{
|
||||
return this->service.async_resolve(this->implementation, e, handler);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_BASIC_RESOLVER_HPP
|
|
@ -564,7 +564,8 @@ public:
|
|||
if (this->service.open(this->implementation,
|
||||
peer_endpoint.protocol(), ec))
|
||||
{
|
||||
this->io_service().post(asio::detail::bind_handler(handler, ec));
|
||||
this->get_io_service().post(
|
||||
asio::detail::bind_handler(handler, ec));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# if defined(_HAS_ITERATOR_DEBUGGING)
|
||||
# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
|
||||
# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
|
||||
# define ASIO_ENABLE_BUFFER_DEBUGGING
|
||||
# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
|
||||
|
@ -390,6 +390,11 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
~buffer_debug_check()
|
||||
{
|
||||
iter_ = Iterator();
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
*iter_;
|
||||
|
|
|
@ -93,10 +93,17 @@ public:
|
|||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
asio::io_service& io_service()
|
||||
{
|
||||
return next_layer_.io_service();
|
||||
return next_layer_.get_io_service();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return next_layer_.get_io_service();
|
||||
}
|
||||
|
||||
/// Close the stream.
|
||||
|
@ -207,7 +214,7 @@ public:
|
|||
buffer(
|
||||
storage_.data() + previous_size,
|
||||
storage_.size() - previous_size),
|
||||
fill_handler<ReadHandler>(io_service(),
|
||||
fill_handler<ReadHandler>(get_io_service(),
|
||||
storage_, previous_size, handler));
|
||||
}
|
||||
|
||||
|
@ -295,12 +302,12 @@ public:
|
|||
if (storage_.empty())
|
||||
{
|
||||
async_fill(read_some_handler<MutableBufferSequence, ReadHandler>(
|
||||
io_service(), storage_, buffers, handler));
|
||||
get_io_service(), storage_, buffers, handler));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t length = copy(buffers);
|
||||
io_service().post(detail::bind_handler(
|
||||
get_io_service().post(detail::bind_handler(
|
||||
handler, asio::error_code(), length));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,10 +83,17 @@ public:
|
|||
return stream_impl_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
asio::io_service& io_service()
|
||||
{
|
||||
return stream_impl_.io_service();
|
||||
return stream_impl_.get_io_service();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return stream_impl_.get_io_service();
|
||||
}
|
||||
|
||||
/// Close the stream.
|
||||
|
|
|
@ -94,10 +94,17 @@ public:
|
|||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
asio::io_service& io_service()
|
||||
{
|
||||
return next_layer_.io_service();
|
||||
return next_layer_.get_io_service();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return next_layer_.get_io_service();
|
||||
}
|
||||
|
||||
/// Close the stream.
|
||||
|
@ -165,7 +172,7 @@ public:
|
|||
void async_flush(WriteHandler handler)
|
||||
{
|
||||
async_write(next_layer_, buffer(storage_.data(), storage_.size()),
|
||||
flush_handler<WriteHandler>(io_service(), storage_, handler));
|
||||
flush_handler<WriteHandler>(get_io_service(), storage_, handler));
|
||||
}
|
||||
|
||||
/// Write the given data to the stream. Returns the number of bytes written.
|
||||
|
@ -253,12 +260,12 @@ public:
|
|||
if (storage_.size() == storage_.capacity())
|
||||
{
|
||||
async_flush(write_some_handler<ConstBufferSequence, WriteHandler>(
|
||||
io_service(), storage_, buffers, handler));
|
||||
get_io_service(), storage_, buffers, handler));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t bytes_copied = copy(buffers);
|
||||
io_service().post(detail::bind_handler(
|
||||
get_io_service().post(detail::bind_handler(
|
||||
handler, asio::error_code(), bytes_copied));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,9 @@ private:
|
|||
#elif defined(ASIO_HAS_KQUEUE)
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::kqueue_reactor<false> > service_impl_type;
|
||||
#elif defined(ASIO_HAS_DEV_POLL)
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::dev_poll_reactor<false> > service_impl_type;
|
||||
#else
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::select_reactor<false> > service_impl_type;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "asio/detail/kqueue_reactor.hpp"
|
||||
#include "asio/detail/select_reactor.hpp"
|
||||
#include "asio/detail/service_base.hpp"
|
||||
#include "asio/detail/win_iocp_io_service.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
|
@ -62,13 +63,16 @@ private:
|
|||
// The type of the platform-specific implementation.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef detail::deadline_timer_service<
|
||||
traits_type, detail::select_reactor<true> > service_impl_type;
|
||||
traits_type, detail::win_iocp_io_service> service_impl_type;
|
||||
#elif defined(ASIO_HAS_EPOLL)
|
||||
typedef detail::deadline_timer_service<
|
||||
traits_type, detail::epoll_reactor<false> > service_impl_type;
|
||||
#elif defined(ASIO_HAS_KQUEUE)
|
||||
typedef detail::deadline_timer_service<
|
||||
traits_type, detail::kqueue_reactor<false> > service_impl_type;
|
||||
#elif defined(ASIO_HAS_DEV_POLL)
|
||||
typedef detail::deadline_timer_service<
|
||||
traits_type, detail::dev_poll_reactor<false> > service_impl_type;
|
||||
#else
|
||||
typedef detail::deadline_timer_service<
|
||||
traits_type, detail::select_reactor<false> > service_impl_type;
|
||||
|
|
|
@ -180,7 +180,7 @@ public:
|
|||
{
|
||||
impl.might_have_pending_waits = true;
|
||||
scheduler_.schedule_timer(timer_queue_, impl.expiry,
|
||||
wait_handler<Handler>(this->io_service(), handler), &impl);
|
||||
wait_handler<Handler>(this->get_io_service(), handler), &impl);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -0,0 +1,647 @@
|
|||
//
|
||||
// dev_poll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2007 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 ASIO_DETAIL_DEV_POLL_REACTOR_HPP
|
||||
#define ASIO_DETAIL_DEV_POLL_REACTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/dev_poll_reactor_fwd.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_DEV_POLL)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <sys/devpoll.h>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_service.hpp"
|
||||
#include "asio/system_error.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/hash_map.hpp"
|
||||
#include "asio/detail/mutex.hpp"
|
||||
#include "asio/detail/task_io_service.hpp"
|
||||
#include "asio/detail/thread.hpp"
|
||||
#include "asio/detail/reactor_op_queue.hpp"
|
||||
#include "asio/detail/select_interrupter.hpp"
|
||||
#include "asio/detail/service_base.hpp"
|
||||
#include "asio/detail/signal_blocker.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
#include "asio/detail/timer_queue.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <bool Own_Thread>
|
||||
class dev_poll_reactor
|
||||
: public asio::detail::service_base<dev_poll_reactor<Own_Thread> >
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
dev_poll_reactor(asio::io_service& io_service)
|
||||
: asio::detail::service_base<
|
||||
dev_poll_reactor<Own_Thread> >(io_service),
|
||||
mutex_(),
|
||||
dev_poll_fd_(do_dev_poll_create()),
|
||||
wait_in_progress_(false),
|
||||
interrupter_(),
|
||||
read_op_queue_(),
|
||||
write_op_queue_(),
|
||||
except_op_queue_(),
|
||||
pending_cancellations_(),
|
||||
stop_thread_(false),
|
||||
thread_(0),
|
||||
shutdown_(false)
|
||||
{
|
||||
// Start the reactor's internal thread only if needed.
|
||||
if (Own_Thread)
|
||||
{
|
||||
asio::detail::signal_blocker sb;
|
||||
thread_ = new asio::detail::thread(
|
||||
bind_handler(&dev_poll_reactor::call_run_thread, this));
|
||||
}
|
||||
|
||||
// Add the interrupter's descriptor to /dev/poll.
|
||||
::pollfd ev = { 0 };
|
||||
ev.fd = interrupter_.read_descriptor();
|
||||
ev.events = POLLIN | POLLERR;
|
||||
ev.revents = 0;
|
||||
::write(dev_poll_fd_, &ev, sizeof(ev));
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~dev_poll_reactor()
|
||||
{
|
||||
shutdown_service();
|
||||
::close(dev_poll_fd_);
|
||||
}
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
void shutdown_service()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
stop_thread_ = true;
|
||||
lock.unlock();
|
||||
|
||||
if (thread_)
|
||||
{
|
||||
interrupter_.interrupt();
|
||||
thread_->join();
|
||||
delete thread_;
|
||||
thread_ = 0;
|
||||
}
|
||||
|
||||
read_op_queue_.destroy_operations();
|
||||
write_op_queue_.destroy_operations();
|
||||
except_op_queue_.destroy_operations();
|
||||
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
timer_queues_[i]->destroy_timers();
|
||||
timer_queues_.clear();
|
||||
}
|
||||
|
||||
// Register a socket with the reactor. Returns 0 on success, system error
|
||||
// code on failure.
|
||||
int register_descriptor(socket_type descriptor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start a new read operation. The handler object will be invoked when the
|
||||
// given descriptor is ready to be read, or an error has occurred.
|
||||
template <typename Handler>
|
||||
void start_read_op(socket_type descriptor, Handler handler)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
return;
|
||||
|
||||
if (!read_op_queue_.has_operation(descriptor))
|
||||
if (handler(asio::error_code()))
|
||||
return;
|
||||
|
||||
if (read_op_queue_.enqueue_operation(descriptor, handler))
|
||||
{
|
||||
::pollfd& ev = add_pending_event_change(descriptor);
|
||||
ev.events = POLLIN | POLLERR | POLLHUP;
|
||||
if (write_op_queue_.has_operation(descriptor))
|
||||
ev.events |= POLLOUT;
|
||||
if (except_op_queue_.has_operation(descriptor))
|
||||
ev.events |= POLLPRI;
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// Start a new write operation. The handler object will be invoked when the
|
||||
// given descriptor is ready to be written, or an error has occurred.
|
||||
template <typename Handler>
|
||||
void start_write_op(socket_type descriptor, Handler handler)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
return;
|
||||
|
||||
if (!write_op_queue_.has_operation(descriptor))
|
||||
if (handler(asio::error_code()))
|
||||
return;
|
||||
|
||||
if (write_op_queue_.enqueue_operation(descriptor, handler))
|
||||
{
|
||||
::pollfd& ev = add_pending_event_change(descriptor);
|
||||
ev.events = POLLOUT | POLLERR | POLLHUP;
|
||||
if (read_op_queue_.has_operation(descriptor))
|
||||
ev.events |= POLLIN;
|
||||
if (except_op_queue_.has_operation(descriptor))
|
||||
ev.events |= POLLPRI;
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// Start a new exception operation. The handler object will be invoked when
|
||||
// the given descriptor has exception information, or an error has occurred.
|
||||
template <typename Handler>
|
||||
void start_except_op(socket_type descriptor, Handler handler)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
return;
|
||||
|
||||
if (except_op_queue_.enqueue_operation(descriptor, handler))
|
||||
{
|
||||
::pollfd& ev = add_pending_event_change(descriptor);
|
||||
ev.events = POLLPRI | POLLERR | POLLHUP;
|
||||
if (read_op_queue_.has_operation(descriptor))
|
||||
ev.events |= POLLIN;
|
||||
if (write_op_queue_.has_operation(descriptor))
|
||||
ev.events |= POLLOUT;
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// Start new write and exception operations. The handler object will be
|
||||
// invoked when the given descriptor is ready for writing or has exception
|
||||
// information available, or an error has occurred.
|
||||
template <typename Handler>
|
||||
void start_write_and_except_ops(socket_type descriptor, Handler handler)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
return;
|
||||
|
||||
bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler);
|
||||
need_mod = except_op_queue_.enqueue_operation(descriptor, handler)
|
||||
&& need_mod;
|
||||
if (need_mod)
|
||||
{
|
||||
::pollfd& ev = add_pending_event_change(descriptor);
|
||||
ev.events = POLLOUT | POLLPRI | POLLERR | POLLHUP;
|
||||
if (read_op_queue_.has_operation(descriptor))
|
||||
ev.events |= POLLIN;
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel all operations associated with the given descriptor. The
|
||||
// handlers associated with the descriptor will be invoked with the
|
||||
// operation_aborted error.
|
||||
void cancel_ops(socket_type descriptor)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
cancel_ops_unlocked(descriptor);
|
||||
}
|
||||
|
||||
// Enqueue cancellation of all operations associated with the given
|
||||
// descriptor. The handlers associated with the descriptor will be invoked
|
||||
// with the operation_aborted error. This function does not acquire the
|
||||
// dev_poll_reactor's mutex, and so should only be used from within a reactor
|
||||
// handler.
|
||||
void enqueue_cancel_ops_unlocked(socket_type descriptor)
|
||||
{
|
||||
pending_cancellations_.push_back(descriptor);
|
||||
}
|
||||
|
||||
// Cancel any operations that are running against the descriptor and remove
|
||||
// its registration from the reactor.
|
||||
void close_descriptor(socket_type descriptor)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
// Remove the descriptor from /dev/poll.
|
||||
::pollfd& ev = add_pending_event_change(descriptor);
|
||||
ev.events = POLLREMOVE;
|
||||
interrupter_.interrupt();
|
||||
|
||||
// Cancel any outstanding operations associated with the descriptor.
|
||||
cancel_ops_unlocked(descriptor);
|
||||
}
|
||||
|
||||
// Add a new timer queue to the reactor.
|
||||
template <typename Time_Traits>
|
||||
void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.push_back(&timer_queue);
|
||||
}
|
||||
|
||||
// Remove a timer queue from the reactor.
|
||||
template <typename Time_Traits>
|
||||
void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
{
|
||||
if (timer_queues_[i] == &timer_queue)
|
||||
{
|
||||
timer_queues_.erase(timer_queues_.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule a timer in the given timer queue to expire at the specified
|
||||
// absolute time. The handler object will be invoked when the timer expires.
|
||||
template <typename Time_Traits, typename Handler>
|
||||
void schedule_timer(timer_queue<Time_Traits>& timer_queue,
|
||||
const typename Time_Traits::time_type& time, Handler handler, void* token)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
if (!shutdown_)
|
||||
if (timer_queue.enqueue_timer(time, handler, token))
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
// Cancel the timer associated with the given token. Returns the number of
|
||||
// handlers that have been posted or dispatched.
|
||||
template <typename Time_Traits>
|
||||
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
std::size_t n = timer_queue.cancel_timer(token);
|
||||
if (n > 0)
|
||||
interrupter_.interrupt();
|
||||
return n;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class task_io_service<dev_poll_reactor<Own_Thread> >;
|
||||
|
||||
// Run /dev/poll once until interrupted or events are ready to be dispatched.
|
||||
void run(bool block)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
// Dispatch any operation cancellations that were made while the select
|
||||
// loop was not running.
|
||||
read_op_queue_.dispatch_cancellations();
|
||||
write_op_queue_.dispatch_cancellations();
|
||||
except_op_queue_.dispatch_cancellations();
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
timer_queues_[i]->dispatch_cancellations();
|
||||
|
||||
// Check if the thread is supposed to stop.
|
||||
if (stop_thread_)
|
||||
{
|
||||
cleanup_operations_and_timers(lock);
|
||||
return;
|
||||
}
|
||||
|
||||
// We can return immediately if there's no work to do and the reactor is
|
||||
// not supposed to block.
|
||||
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
|
||||
&& except_op_queue_.empty() && all_timer_queues_are_empty())
|
||||
{
|
||||
cleanup_operations_and_timers(lock);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the pending event registration changes to the /dev/poll descriptor.
|
||||
std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
|
||||
errno = 0;
|
||||
int result = ::write(dev_poll_fd_,
|
||||
&pending_event_changes_[0], events_size);
|
||||
if (result != static_cast<int>(events_size))
|
||||
{
|
||||
for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
|
||||
{
|
||||
int descriptor = pending_event_changes_[i].fd;
|
||||
asio::error_code ec = asio::error_code(
|
||||
errno, asio::error::get_system_category());
|
||||
read_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
pending_event_changes_.clear();
|
||||
pending_event_change_index_.clear();
|
||||
|
||||
int timeout = block ? get_timeout() : 0;
|
||||
wait_in_progress_ = true;
|
||||
lock.unlock();
|
||||
|
||||
// Block on the /dev/poll descriptor.
|
||||
::pollfd events[128] = { { 0 } };
|
||||
::dvpoll dp = { 0 };
|
||||
dp.dp_fds = events;
|
||||
dp.dp_nfds = 128;
|
||||
dp.dp_timeout = timeout;
|
||||
int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
|
||||
|
||||
lock.lock();
|
||||
wait_in_progress_ = false;
|
||||
|
||||
// Block signals while dispatching operations.
|
||||
asio::detail::signal_blocker sb;
|
||||
|
||||
// Dispatch the waiting events.
|
||||
for (int i = 0; i < num_events; ++i)
|
||||
{
|
||||
int descriptor = events[i].fd;
|
||||
if (descriptor == interrupter_.read_descriptor())
|
||||
{
|
||||
interrupter_.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool more_reads = false;
|
||||
bool more_writes = false;
|
||||
bool more_except = false;
|
||||
asio::error_code ec;
|
||||
|
||||
// Exception operations must be processed first to ensure that any
|
||||
// out-of-band data is read before normal data.
|
||||
if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
|
||||
more_except = except_op_queue_.dispatch_operation(descriptor, ec);
|
||||
else
|
||||
more_except = except_op_queue_.has_operation(descriptor);
|
||||
|
||||
if (events[i].events & (POLLIN | POLLERR | POLLHUP))
|
||||
more_reads = read_op_queue_.dispatch_operation(descriptor, ec);
|
||||
else
|
||||
more_reads = read_op_queue_.has_operation(descriptor);
|
||||
|
||||
if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
|
||||
more_writes = write_op_queue_.dispatch_operation(descriptor, ec);
|
||||
else
|
||||
more_writes = write_op_queue_.has_operation(descriptor);
|
||||
|
||||
if ((events[i].events == POLLHUP)
|
||||
&& !more_except && !more_reads && !more_writes)
|
||||
{
|
||||
// If we have only an POLLHUP event and no operations associated
|
||||
// with the descriptor then we need to delete the descriptor from
|
||||
// /dev/poll. The poll operation might produce POLLHUP events even
|
||||
// if they are not specifically requested, so if we do not remove the
|
||||
// descriptor we can end up in a tight polling loop.
|
||||
::pollfd ev = { 0 };
|
||||
ev.fd = descriptor;
|
||||
ev.events = POLLREMOVE;
|
||||
ev.revents = 0;
|
||||
::write(dev_poll_fd_, &ev, sizeof(ev));
|
||||
}
|
||||
else
|
||||
{
|
||||
::pollfd ev = { 0 };
|
||||
ev.fd = descriptor;
|
||||
ev.events = POLLERR | POLLHUP;
|
||||
if (more_reads)
|
||||
ev.events |= POLLIN;
|
||||
if (more_writes)
|
||||
ev.events |= POLLOUT;
|
||||
if (more_except)
|
||||
ev.events |= POLLPRI;
|
||||
ev.revents = 0;
|
||||
int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
|
||||
if (result != sizeof(ev))
|
||||
{
|
||||
ec = asio::error_code(errno,
|
||||
asio::error::get_system_category());
|
||||
read_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
read_op_queue_.dispatch_cancellations();
|
||||
write_op_queue_.dispatch_cancellations();
|
||||
except_op_queue_.dispatch_cancellations();
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
{
|
||||
timer_queues_[i]->dispatch_timers();
|
||||
timer_queues_[i]->dispatch_cancellations();
|
||||
}
|
||||
|
||||
// Issue any pending cancellations.
|
||||
for (size_t i = 0; i < pending_cancellations_.size(); ++i)
|
||||
cancel_ops_unlocked(pending_cancellations_[i]);
|
||||
pending_cancellations_.clear();
|
||||
|
||||
cleanup_operations_and_timers(lock);
|
||||
}
|
||||
|
||||
// Run the select loop in the thread.
|
||||
void run_thread()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
while (!stop_thread_)
|
||||
{
|
||||
lock.unlock();
|
||||
run(true);
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
|
||||
// Entry point for the select loop thread.
|
||||
static void call_run_thread(dev_poll_reactor* reactor)
|
||||
{
|
||||
reactor->run_thread();
|
||||
}
|
||||
|
||||
// Interrupt the select loop.
|
||||
void interrupt()
|
||||
{
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
// Create the /dev/poll file descriptor. Throws an exception if the descriptor
|
||||
// cannot be created.
|
||||
static int do_dev_poll_create()
|
||||
{
|
||||
int fd = ::open("/dev/poll", O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
boost::throw_exception(
|
||||
asio::system_error(
|
||||
asio::error_code(errno,
|
||||
asio::error::get_system_category()),
|
||||
"/dev/poll"));
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Check if all timer queues are empty.
|
||||
bool all_timer_queues_are_empty() const
|
||||
{
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
if (!timer_queues_[i]->empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the timeout value for the /dev/poll DP_POLL operation. The timeout
|
||||
// value is returned as a number of milliseconds. A return value of -1
|
||||
// indicates that the poll should block indefinitely.
|
||||
int get_timeout()
|
||||
{
|
||||
if (all_timer_queues_are_empty())
|
||||
return -1;
|
||||
|
||||
// By default we will wait no longer than 5 minutes. This will ensure that
|
||||
// any changes to the system clock are detected after no longer than this.
|
||||
boost::posix_time::time_duration minimum_wait_duration
|
||||
= boost::posix_time::minutes(5);
|
||||
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
{
|
||||
boost::posix_time::time_duration wait_duration
|
||||
= timer_queues_[i]->wait_duration();
|
||||
if (wait_duration < minimum_wait_duration)
|
||||
minimum_wait_duration = wait_duration;
|
||||
}
|
||||
|
||||
if (minimum_wait_duration > boost::posix_time::time_duration())
|
||||
{
|
||||
int milliseconds = minimum_wait_duration.total_milliseconds();
|
||||
return milliseconds > 0 ? milliseconds : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel all operations associated with the given descriptor. The do_cancel
|
||||
// function of the handler objects will be invoked. This function does not
|
||||
// acquire the dev_poll_reactor's mutex.
|
||||
void cancel_ops_unlocked(socket_type descriptor)
|
||||
{
|
||||
bool interrupt = read_op_queue_.cancel_operations(descriptor);
|
||||
interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
|
||||
interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
|
||||
if (interrupt)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
// Clean up operations and timers. We must not hold the lock since the
|
||||
// destructors may make calls back into this reactor. We make a copy of the
|
||||
// vector of timer queues since the original may be modified while the lock
|
||||
// is not held.
|
||||
void cleanup_operations_and_timers(
|
||||
asio::detail::mutex::scoped_lock& lock)
|
||||
{
|
||||
timer_queues_for_cleanup_ = timer_queues_;
|
||||
lock.unlock();
|
||||
read_op_queue_.cleanup_operations();
|
||||
write_op_queue_.cleanup_operations();
|
||||
except_op_queue_.cleanup_operations();
|
||||
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
|
||||
timer_queues_for_cleanup_[i]->cleanup_timers();
|
||||
}
|
||||
|
||||
// Add a pending event entry for the given descriptor.
|
||||
::pollfd& add_pending_event_change(int descriptor)
|
||||
{
|
||||
hash_map<int, std::size_t>::iterator iter
|
||||
= pending_event_change_index_.find(descriptor);
|
||||
if (iter == pending_event_change_index_.end())
|
||||
{
|
||||
std::size_t index = pending_event_changes_.size();
|
||||
pending_event_changes_.reserve(pending_event_changes_.size() + 1);
|
||||
pending_event_change_index_.insert(std::make_pair(descriptor, index));
|
||||
pending_event_changes_.push_back(::pollfd());
|
||||
pending_event_changes_[index].fd = descriptor;
|
||||
pending_event_changes_[index].revents = 0;
|
||||
return pending_event_changes_[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return pending_event_changes_[iter->second];
|
||||
}
|
||||
}
|
||||
|
||||
// Mutex to protect access to internal data.
|
||||
asio::detail::mutex mutex_;
|
||||
|
||||
// The /dev/poll file descriptor.
|
||||
int dev_poll_fd_;
|
||||
|
||||
// Vector of /dev/poll events waiting to be written to the descriptor.
|
||||
std::vector< ::pollfd> pending_event_changes_;
|
||||
|
||||
// Hash map to associate a descriptor with a pending event change index.
|
||||
hash_map<int, std::size_t> pending_event_change_index_;
|
||||
|
||||
// Whether the DP_POLL operation is currently in progress
|
||||
bool wait_in_progress_;
|
||||
|
||||
// The interrupter is used to break a blocking DP_POLL operation.
|
||||
select_interrupter interrupter_;
|
||||
|
||||
// The queue of read operations.
|
||||
reactor_op_queue<socket_type> read_op_queue_;
|
||||
|
||||
// The queue of write operations.
|
||||
reactor_op_queue<socket_type> write_op_queue_;
|
||||
|
||||
// The queue of except operations.
|
||||
reactor_op_queue<socket_type> except_op_queue_;
|
||||
|
||||
// The timer queues.
|
||||
std::vector<timer_queue_base*> timer_queues_;
|
||||
|
||||
// A copy of the timer queues, used when cleaning up timers. The copy is
|
||||
// stored as a class data member to avoid unnecessary memory allocation.
|
||||
std::vector<timer_queue_base*> timer_queues_for_cleanup_;
|
||||
|
||||
// The descriptors that are pending cancellation.
|
||||
std::vector<socket_type> pending_cancellations_;
|
||||
|
||||
// Does the reactor loop thread need to stop.
|
||||
bool stop_thread_;
|
||||
|
||||
// The thread that is running the reactor loop.
|
||||
asio::detail::thread* thread_;
|
||||
|
||||
// Whether the service has been shut down.
|
||||
bool shutdown_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#endif // defined(ASIO_HAS_DEV_POLL)
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_DEV_POLL_REACTOR_HPP
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// dev_poll_reactor_fwd.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2007 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 ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
|
||||
#define ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#if !defined(ASIO_DISABLE_DEV_POLL)
|
||||
#if defined(__sun) // This service is only supported on Solaris.
|
||||
|
||||
// Define this to indicate that /dev/poll is supported on the target platform.
|
||||
#define ASIO_HAS_DEV_POLL 1
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <bool Own_Thread>
|
||||
class dev_poll_reactor;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#endif // defined(__sun)
|
||||
#endif // !defined(ASIO_DISABLE_DEV_POLL)
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
|
|
@ -155,10 +155,12 @@ public:
|
|||
ev.data.fd = descriptor;
|
||||
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
if (result != 0 && errno == ENOENT)
|
||||
result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
read_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
|
@ -189,10 +191,12 @@ public:
|
|||
ev.data.fd = descriptor;
|
||||
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
if (result != 0 && errno == ENOENT)
|
||||
result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
|
@ -219,10 +223,12 @@ public:
|
|||
ev.data.fd = descriptor;
|
||||
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
if (result != 0 && errno == ENOENT)
|
||||
result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
|
@ -251,10 +257,12 @@ public:
|
|||
ev.data.fd = descriptor;
|
||||
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
if (result != 0 && errno == ENOENT)
|
||||
result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
|
@ -419,23 +427,40 @@ private:
|
|||
else
|
||||
more_writes = write_op_queue_.has_operation(descriptor);
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLERR | EPOLLHUP;
|
||||
if (more_reads)
|
||||
ev.events |= EPOLLIN;
|
||||
if (more_writes)
|
||||
ev.events |= EPOLLOUT;
|
||||
if (more_except)
|
||||
ev.events |= EPOLLPRI;
|
||||
ev.data.fd = descriptor;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
if ((events[i].events == EPOLLHUP)
|
||||
&& !more_except && !more_reads && !more_writes)
|
||||
{
|
||||
ec = asio::error_code(errno,
|
||||
asio::error::system_category);
|
||||
read_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
// If we have only an EPOLLHUP event and no operations associated
|
||||
// with the descriptor then we need to delete the descriptor from
|
||||
// epoll. The epoll_wait system call will produce EPOLLHUP events
|
||||
// even if they are not specifically requested, so if we do not
|
||||
// remove the descriptor we can end up in a tight loop of repeated
|
||||
// calls to epoll_wait.
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
|
||||
}
|
||||
else
|
||||
{
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLERR | EPOLLHUP;
|
||||
if (more_reads)
|
||||
ev.events |= EPOLLIN;
|
||||
if (more_writes)
|
||||
ev.events |= EPOLLOUT;
|
||||
if (more_except)
|
||||
ev.events |= EPOLLPRI;
|
||||
ev.data.fd = descriptor;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
if (result != 0 && errno == ENOENT)
|
||||
result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
{
|
||||
ec = asio::error_code(errno,
|
||||
asio::error::get_system_category());
|
||||
read_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -493,7 +518,7 @@ private:
|
|||
boost::throw_exception(
|
||||
asio::system_error(
|
||||
asio::error_code(errno,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"epoll"));
|
||||
}
|
||||
return fd;
|
||||
|
@ -531,7 +556,8 @@ private:
|
|||
|
||||
if (minimum_wait_duration > boost::posix_time::time_duration())
|
||||
{
|
||||
return minimum_wait_duration.total_milliseconds();
|
||||
int milliseconds = minimum_wait_duration.total_milliseconds();
|
||||
return milliseconds > 0 ? milliseconds : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
//
|
||||
// handler_queue.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2007 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 ASIO_DETAIL_HANDLER_QUEUE_HPP
|
||||
#define ASIO_DETAIL_HANDLER_QUEUE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class handler_queue
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// Base class for handlers in the queue.
|
||||
class handler
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
void invoke()
|
||||
{
|
||||
invoke_func_(this);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
destroy_func_(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef void (*invoke_func_type)(handler*);
|
||||
typedef void (*destroy_func_type)(handler*);
|
||||
|
||||
handler(invoke_func_type invoke_func,
|
||||
destroy_func_type destroy_func)
|
||||
: next_(0),
|
||||
invoke_func_(invoke_func),
|
||||
destroy_func_(destroy_func)
|
||||
{
|
||||
}
|
||||
|
||||
~handler()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class handler_queue;
|
||||
handler* next_;
|
||||
invoke_func_type invoke_func_;
|
||||
destroy_func_type destroy_func_;
|
||||
};
|
||||
|
||||
// Smart point to manager handler lifetimes.
|
||||
class scoped_ptr
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
explicit scoped_ptr(handler* h)
|
||||
: handler_(h)
|
||||
{
|
||||
}
|
||||
|
||||
~scoped_ptr()
|
||||
{
|
||||
if (handler_)
|
||||
handler_->destroy();
|
||||
}
|
||||
|
||||
handler* get() const
|
||||
{
|
||||
return handler_;
|
||||
}
|
||||
|
||||
handler* release()
|
||||
{
|
||||
handler* tmp = handler_;
|
||||
handler_ = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
handler* handler_;
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
handler_queue()
|
||||
: front_(0),
|
||||
back_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Wrap a handler to be pushed into the queue.
|
||||
template <typename Handler>
|
||||
static handler* wrap(Handler h)
|
||||
{
|
||||
// Allocate and construct an object to wrap the handler.
|
||||
typedef handler_wrapper<Handler> value_type;
|
||||
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
|
||||
raw_handler_ptr<alloc_traits> raw_ptr(h);
|
||||
handler_ptr<alloc_traits> ptr(raw_ptr, h);
|
||||
return ptr.release();
|
||||
}
|
||||
|
||||
// Get the handler at the front of the queue.
|
||||
handler* front()
|
||||
{
|
||||
return front_;
|
||||
}
|
||||
|
||||
// Pop a handler from the front of the queue.
|
||||
void pop()
|
||||
{
|
||||
if (front_)
|
||||
{
|
||||
handler* tmp = front_;
|
||||
front_ = front_->next_;
|
||||
if (front_ == 0)
|
||||
back_ = 0;
|
||||
tmp->next_= 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Push a handler on to the back of the queue.
|
||||
void push(handler* h)
|
||||
{
|
||||
h->next_ = 0;
|
||||
if (back_)
|
||||
{
|
||||
back_->next_ = h;
|
||||
back_ = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
front_ = back_ = h;
|
||||
}
|
||||
}
|
||||
|
||||
// Whether the queue is empty.
|
||||
bool empty() const
|
||||
{
|
||||
return front_ == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Template wrapper for handlers.
|
||||
template <typename Handler>
|
||||
class handler_wrapper
|
||||
: public handler
|
||||
{
|
||||
public:
|
||||
handler_wrapper(Handler h)
|
||||
: handler(
|
||||
&handler_wrapper<Handler>::do_call,
|
||||
&handler_wrapper<Handler>::do_destroy),
|
||||
handler_(h)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_call(handler* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made.
|
||||
Handler handler(h->handler_);
|
||||
|
||||
// Free the memory associated with the handler.
|
||||
ptr.reset();
|
||||
|
||||
// Make the upcall.
|
||||
asio_handler_invoke_helpers::invoke(handler, &handler);
|
||||
}
|
||||
|
||||
static void do_destroy(handler* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
// The front of the queue.
|
||||
handler* front_;
|
||||
|
||||
// The back of the queue.
|
||||
handler* back_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_HANDLER_QUEUE_HPP
|
|
@ -151,7 +151,7 @@ public:
|
|||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
read_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ public:
|
|||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ public:
|
|||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ public:
|
|||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ public:
|
|||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
except_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
write_op_queue_.dispatch_all_operations(descriptor, ec);
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ private:
|
|||
if (events[i].flags & EV_ERROR)
|
||||
{
|
||||
asio::error_code error(
|
||||
events[i].data, asio::error::system_category);
|
||||
events[i].data, asio::error::get_system_category());
|
||||
except_op_queue_.dispatch_all_operations(descriptor, error);
|
||||
read_op_queue_.dispatch_all_operations(descriptor, error);
|
||||
}
|
||||
|
@ -428,7 +428,7 @@ private:
|
|||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code error(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
except_op_queue_.dispatch_all_operations(descriptor, error);
|
||||
read_op_queue_.dispatch_all_operations(descriptor, error);
|
||||
}
|
||||
|
@ -440,7 +440,7 @@ private:
|
|||
if (events[i].flags & EV_ERROR)
|
||||
{
|
||||
asio::error_code error(
|
||||
events[i].data, asio::error::system_category);
|
||||
events[i].data, asio::error::get_system_category());
|
||||
write_op_queue_.dispatch_all_operations(descriptor, error);
|
||||
}
|
||||
else
|
||||
|
@ -458,7 +458,7 @@ private:
|
|||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code error(errno,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
write_op_queue_.dispatch_all_operations(descriptor, error);
|
||||
}
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ private:
|
|||
boost::throw_exception(
|
||||
asio::system_error(
|
||||
asio::error_code(errno,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"kqueue"));
|
||||
}
|
||||
return fd;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
@ -27,6 +28,8 @@
|
|||
#include <fcntl.h>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/system_error.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
@ -46,6 +49,13 @@ public:
|
|||
write_descriptor_ = pipe_fds[1];
|
||||
::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::get_system_category());
|
||||
asio::system_error e(ec, "pipe_select_interrupter");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
|
|
|
@ -48,7 +48,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"event");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
fd_set fd_set_;
|
||||
mutable fd_set fd_set_;
|
||||
socket_type max_descriptor_;
|
||||
};
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"mutex");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
@ -70,7 +71,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"mutex");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
@ -83,7 +85,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"mutex");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"thread");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"tss");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -157,7 +157,8 @@ public:
|
|||
|
||||
if (int err = reactor_.register_descriptor(sock.get()))
|
||||
{
|
||||
ec = asio::error_code(err, asio::error::system_category);
|
||||
ec = asio::error_code(err,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
@ -181,7 +182,8 @@ public:
|
|||
|
||||
if (int err = reactor_.register_descriptor(native_socket))
|
||||
{
|
||||
ec = asio::error_code(err, asio::error::system_category);
|
||||
ec = asio::error_code(err,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
@ -450,7 +452,7 @@ public:
|
|||
}
|
||||
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
|
@ -468,7 +470,7 @@ public:
|
|||
}
|
||||
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
|
@ -624,7 +626,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
}
|
||||
else
|
||||
|
@ -645,7 +647,7 @@ public:
|
|||
// A request to receive 0 bytes on a stream socket is a no-op.
|
||||
if (total_buffer_size == 0)
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error_code(), 0));
|
||||
return;
|
||||
}
|
||||
|
@ -658,7 +660,7 @@ public:
|
|||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec, 0));
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
|
@ -666,7 +668,7 @@ public:
|
|||
|
||||
reactor_.start_write_op(impl.socket_,
|
||||
send_handler<ConstBufferSequence, Handler>(
|
||||
impl.socket_, this->io_service(), buffers, flags, handler));
|
||||
impl.socket_, this->get_io_service(), buffers, flags, handler));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -804,7 +806,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
}
|
||||
else
|
||||
|
@ -816,7 +818,7 @@ public:
|
|||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec, 0));
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
|
@ -824,7 +826,7 @@ public:
|
|||
|
||||
reactor_.start_write_op(impl.socket_,
|
||||
send_to_handler<ConstBufferSequence, Handler>(
|
||||
impl.socket_, this->io_service(), buffers,
|
||||
impl.socket_, this->get_io_service(), buffers,
|
||||
destination, flags, handler));
|
||||
}
|
||||
}
|
||||
|
@ -975,7 +977,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
}
|
||||
else
|
||||
|
@ -996,7 +998,7 @@ public:
|
|||
// A request to receive 0 bytes on a stream socket is a no-op.
|
||||
if (total_buffer_size == 0)
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error_code(), 0));
|
||||
return;
|
||||
}
|
||||
|
@ -1009,7 +1011,7 @@ public:
|
|||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec, 0));
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
|
@ -1019,13 +1021,13 @@ public:
|
|||
{
|
||||
reactor_.start_except_op(impl.socket_,
|
||||
receive_handler<MutableBufferSequence, Handler>(
|
||||
impl.socket_, this->io_service(), buffers, flags, handler));
|
||||
impl.socket_, this->get_io_service(), buffers, flags, handler));
|
||||
}
|
||||
else
|
||||
{
|
||||
reactor_.start_read_op(impl.socket_,
|
||||
receive_handler<MutableBufferSequence, Handler>(
|
||||
impl.socket_, this->io_service(), buffers, flags, handler));
|
||||
impl.socket_, this->get_io_service(), buffers, flags, handler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1073,7 +1075,7 @@ public:
|
|||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
socket_addr_len_type addr_len = sender_endpoint.capacity();
|
||||
std::size_t addr_len = sender_endpoint.capacity();
|
||||
int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags,
|
||||
sender_endpoint.data(), &addr_len, ec);
|
||||
|
||||
|
@ -1144,7 +1146,7 @@ public:
|
|||
}
|
||||
|
||||
// Receive some data.
|
||||
socket_addr_len_type addr_len = sender_endpoint_.capacity();
|
||||
std::size_t addr_len = sender_endpoint_.capacity();
|
||||
asio::error_code ec;
|
||||
int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
|
||||
sender_endpoint_.data(), &addr_len, ec);
|
||||
|
@ -1181,7 +1183,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
}
|
||||
else
|
||||
|
@ -1193,7 +1195,7 @@ public:
|
|||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec, 0));
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
|
@ -1201,7 +1203,7 @@ public:
|
|||
|
||||
reactor_.start_read_op(impl.socket_,
|
||||
receive_from_handler<MutableBufferSequence, Handler>(
|
||||
impl.socket_, this->io_service(), buffers,
|
||||
impl.socket_, this->get_io_service(), buffers,
|
||||
sender_endpoint, flags, handler));
|
||||
}
|
||||
}
|
||||
|
@ -1242,7 +1244,7 @@ public:
|
|||
// Try to complete the operation without blocking.
|
||||
asio::error_code ec;
|
||||
socket_holder new_socket;
|
||||
socket_addr_len_type addr_len = 0;
|
||||
std::size_t addr_len = 0;
|
||||
if (peer_endpoint)
|
||||
{
|
||||
addr_len = peer_endpoint->capacity();
|
||||
|
@ -1327,7 +1329,7 @@ public:
|
|||
// Accept the waiting connection.
|
||||
asio::error_code ec;
|
||||
socket_holder new_socket;
|
||||
socket_addr_len_type addr_len = 0;
|
||||
std::size_t addr_len = 0;
|
||||
if (peer_endpoint_)
|
||||
{
|
||||
addr_len = peer_endpoint_->capacity();
|
||||
|
@ -1384,12 +1386,12 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor));
|
||||
}
|
||||
else if (peer.is_open())
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::already_open));
|
||||
}
|
||||
else
|
||||
|
@ -1401,7 +1403,7 @@ public:
|
|||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec));
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
|
@ -1409,7 +1411,7 @@ public:
|
|||
|
||||
reactor_.start_read_op(impl.socket_,
|
||||
accept_handler<Socket, Handler>(
|
||||
impl.socket_, this->io_service(),
|
||||
impl.socket_, this->get_io_service(),
|
||||
peer, impl.protocol_, peer_endpoint,
|
||||
(impl.flags_ & implementation_type::enable_connection_aborted) != 0,
|
||||
handler));
|
||||
|
@ -1489,7 +1491,7 @@ public:
|
|||
if (connect_error)
|
||||
{
|
||||
ec = asio::error_code(connect_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
io_service_.post(bind_handler(handler_, ec));
|
||||
return true;
|
||||
}
|
||||
|
@ -1515,7 +1517,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor));
|
||||
return;
|
||||
}
|
||||
|
@ -1527,7 +1529,7 @@ public:
|
|||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec));
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
|
@ -1541,7 +1543,7 @@ public:
|
|||
{
|
||||
// The connect operation has finished successfully so we need to post the
|
||||
// handler immediately.
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error_code()));
|
||||
}
|
||||
else if (ec == asio::error::in_progress
|
||||
|
@ -1551,13 +1553,13 @@ public:
|
|||
// until the socket becomes writeable.
|
||||
boost::shared_ptr<bool> completed(new bool(false));
|
||||
reactor_.start_write_and_except_ops(impl.socket_,
|
||||
connect_handler<Handler>(
|
||||
impl.socket_, completed, this->io_service(), reactor_, handler));
|
||||
connect_handler<Handler>(impl.socket_, completed,
|
||||
this->get_io_service(), reactor_, handler));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The connect operation has failed, so post the handler immediately.
|
||||
this->io_service().post(bind_handler(handler, ec));
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ public:
|
|||
start_work_thread();
|
||||
work_io_service_->post(
|
||||
resolve_query_handler<Handler>(
|
||||
impl, query, this->io_service(), handler));
|
||||
impl, query, this->get_io_service(), handler));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,7 +309,7 @@ public:
|
|||
start_work_thread();
|
||||
work_io_service_->post(
|
||||
resolve_endpoint_handler<Handler>(
|
||||
impl, endpoint, this->io_service(), handler));
|
||||
impl, endpoint, this->get_io_service(), handler));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,6 @@
|
|||
#include <cerrno>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <new>
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif // defined(__MACH__) && defined(__APPLE__)
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error.hpp"
|
||||
|
@ -38,12 +35,24 @@ namespace asio {
|
|||
namespace detail {
|
||||
namespace socket_ops {
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
struct msghdr { int msg_namelen; };
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
||||
#if defined(__hpux)
|
||||
// HP-UX doesn't declare these functions extern "C", so they are declared again
|
||||
// here to avoid linker errors about undefined symbols.
|
||||
extern "C" char* if_indextoname(unsigned int, char*);
|
||||
extern "C" unsigned int if_nametoindex(const char*);
|
||||
#endif // defined(__hpux)
|
||||
|
||||
inline void clear_error(asio::error_code& ec)
|
||||
{
|
||||
errno = 0;
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
WSASetLastError(0);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
#else
|
||||
errno = 0;
|
||||
#endif
|
||||
ec = asio::error_code();
|
||||
}
|
||||
|
||||
|
@ -53,22 +62,36 @@ inline ReturnType error_wrapper(ReturnType return_value,
|
|||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
ec = asio::error_code(WSAGetLastError(),
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
#else
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = asio::error_code(errno,
|
||||
asio::error::get_system_category());
|
||||
#endif
|
||||
return return_value;
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline socket_type call_accept(SockLenType msghdr::*,
|
||||
socket_type s, socket_addr_type* addr, std::size_t* addrlen)
|
||||
{
|
||||
SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
|
||||
socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
|
||||
if (addrlen)
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline socket_type accept(socket_type s, socket_addr_type* addr,
|
||||
socket_addr_len_type* addrlen, asio::error_code& ec)
|
||||
std::size_t* addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
|
||||
socket_type new_s = error_wrapper(::accept(s, addr, addrlen), ec);
|
||||
|
||||
socket_type new_s = error_wrapper(call_accept(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
if (new_s == invalid_socket)
|
||||
return new_s;
|
||||
|
||||
#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
|
||||
int optval = 1;
|
||||
int result = error_wrapper(::setsockopt(new_s,
|
||||
SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
|
||||
|
@ -77,25 +100,45 @@ inline socket_type accept(socket_type s, socket_addr_type* addr,
|
|||
::close(new_s);
|
||||
return invalid_socket;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
|
||||
return new_s;
|
||||
#else
|
||||
return error_wrapper(::accept(s, addr, addrlen), ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_bind(SockLenType msghdr::*,
|
||||
socket_type s, const socket_addr_type* addr, std::size_t addrlen)
|
||||
{
|
||||
return ::bind(s, addr, (SockLenType)addrlen);
|
||||
}
|
||||
|
||||
inline int bind(socket_type s, const socket_addr_type* addr,
|
||||
socket_addr_len_type addrlen, asio::error_code& ec)
|
||||
std::size_t addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::bind(s, addr, addrlen), ec);
|
||||
int result = error_wrapper(call_bind(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int close(socket_type s, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(::closesocket(s), ec);
|
||||
int result = error_wrapper(::closesocket(s), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(::close(s), ec);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
@ -104,20 +147,43 @@ inline int close(socket_type s, asio::error_code& ec)
|
|||
inline int shutdown(socket_type s, int what, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::shutdown(s, what), ec);
|
||||
int result = error_wrapper(::shutdown(s, what), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_connect(SockLenType msghdr::*,
|
||||
socket_type s, const socket_addr_type* addr, std::size_t addrlen)
|
||||
{
|
||||
return ::connect(s, addr, (SockLenType)addrlen);
|
||||
}
|
||||
|
||||
inline int connect(socket_type s, const socket_addr_type* addr,
|
||||
socket_addr_len_type addrlen, asio::error_code& ec)
|
||||
std::size_t addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::connect(s, addr, addrlen), ec);
|
||||
int result = error_wrapper(call_connect(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int listen(socket_type s, int backlog, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::listen(s, backlog), ec);
|
||||
int result = error_wrapper(::listen(s, backlog), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
@ -148,6 +214,28 @@ inline void init_buf(buf& b, const void* data, size_t size)
|
|||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
|
||||
{
|
||||
name = addr;
|
||||
}
|
||||
|
||||
inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
|
||||
{
|
||||
name = const_cast<socket_addr_type*>(addr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
|
||||
{
|
||||
name = reinterpret_cast<T>(addr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
|
||||
{
|
||||
name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
|
||||
}
|
||||
|
||||
inline int recv(socket_type s, buf* bufs, size_t count, int flags,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
|
@ -161,22 +249,20 @@ inline int recv(socket_type s, buf* bufs, size_t count, int flags,
|
|||
recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
msg.msg_name = 0;
|
||||
msg.msg_namelen = 0;
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
return error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
|
||||
socket_addr_type* addr, socket_addr_len_type* addrlen,
|
||||
socket_addr_type* addr, std::size_t* addrlen,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
|
@ -185,25 +271,22 @@ inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
|
|||
DWORD recv_buf_count = static_cast<DWORD>(count);
|
||||
DWORD bytes_transferred = 0;
|
||||
DWORD recv_flags = flags;
|
||||
int tmp_addrlen = (int)*addrlen;
|
||||
int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
|
||||
&bytes_transferred, &recv_flags, addr, addrlen, 0, 0), ec);
|
||||
&bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
#if defined(__MACH__) && defined(__APPLE__) \
|
||||
&& (MAC_OS_X_VERSION_MAX_ALLOWED < 1040)
|
||||
msg.msg_name = reinterpret_cast<char*>(addr);
|
||||
#else
|
||||
msg.msg_name = addr;
|
||||
#endif
|
||||
msghdr msg = msghdr();
|
||||
init_msghdr_msg_name(msg.msg_name, addr);
|
||||
msg.msg_namelen = *addrlen;
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
*addrlen = msg.msg_namelen;
|
||||
return result;
|
||||
|
@ -223,16 +306,14 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags,
|
|||
send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
msg.msg_name = 0;
|
||||
msg.msg_namelen = 0;
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = const_cast<buf*>(bufs);
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
#if defined(__linux__)
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif // defined(__linux__)
|
||||
|
@ -241,7 +322,7 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags,
|
|||
}
|
||||
|
||||
inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
const socket_addr_type* addr, socket_addr_len_type addrlen,
|
||||
const socket_addr_type* addr, std::size_t addrlen,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
|
@ -250,24 +331,20 @@ inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
|
|||
DWORD send_buf_count = static_cast<DWORD>(count);
|
||||
DWORD bytes_transferred = 0;
|
||||
int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
|
||||
send_buf_count, &bytes_transferred, flags, addr, addrlen, 0, 0), ec);
|
||||
send_buf_count, &bytes_transferred, flags, addr,
|
||||
static_cast<int>(addrlen), 0, 0), ec);
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
#if defined(__MACH__) && defined(__APPLE__) \
|
||||
&& (MAC_OS_X_VERSION_MAX_ALLOWED < 1040)
|
||||
msg.msg_name = reinterpret_cast<char*>(const_cast<socket_addr_type*>(addr));
|
||||
#else
|
||||
msg.msg_name = const_cast<socket_addr_type*>(addr);
|
||||
#endif
|
||||
msghdr msg = msghdr();
|
||||
init_msghdr_msg_name(msg.msg_name, addr);
|
||||
msg.msg_namelen = addrlen;
|
||||
msg.msg_iov = const_cast<buf*>(bufs);
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
#if defined(__linux__)
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif // defined(__linux__)
|
||||
|
@ -295,6 +372,10 @@ inline socket_type socket(int af, int type, int protocol,
|
|||
reinterpret_cast<const char*>(&optval), sizeof(optval));
|
||||
}
|
||||
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
|
||||
return s;
|
||||
#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
|
||||
socket_type s = error_wrapper(::socket(af, type, protocol), ec);
|
||||
|
@ -316,8 +397,17 @@ inline socket_type socket(int af, int type, int protocol,
|
|||
#endif
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_setsockopt(SockLenType msghdr::*,
|
||||
socket_type s, int level, int optname,
|
||||
const void* optval, std::size_t optlen)
|
||||
{
|
||||
return ::setsockopt(s, level, optname,
|
||||
(const char*)optval, (SockLenType)optlen);
|
||||
}
|
||||
|
||||
inline int setsockopt(socket_type s, int level, int optname,
|
||||
const void* optval, size_t optlen, asio::error_code& ec)
|
||||
const void* optval, std::size_t optlen, asio::error_code& ec)
|
||||
{
|
||||
if (level == custom_socket_option_level && optname == always_fail_option)
|
||||
{
|
||||
|
@ -342,15 +432,27 @@ inline int setsockopt(socket_type s, int level, int optname,
|
|||
}
|
||||
ec = asio::error::fault;
|
||||
return -1;
|
||||
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
#else // defined(__BORLANDC__)
|
||||
clear_error(ec);
|
||||
return error_wrapper(::setsockopt(s, level, optname,
|
||||
reinterpret_cast<const char*>(optval), static_cast<int>(optlen)), ec);
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
clear_error(ec);
|
||||
return error_wrapper(::setsockopt(s, level, optname, optval,
|
||||
static_cast<socklen_t>(optlen)), ec);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
|
||||
s, level, optname, optval, optlen), ec);
|
||||
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#endif // defined(__BORLANDC__)
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_getsockopt(SockLenType msghdr::*,
|
||||
socket_type s, int level, int optname,
|
||||
void* optval, std::size_t* optlen)
|
||||
{
|
||||
SockLenType tmp_optlen = (SockLenType)*optlen;
|
||||
int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
|
||||
*optlen = (std::size_t)tmp_optlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
||||
|
@ -394,10 +496,8 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
|||
return -1;
|
||||
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
clear_error(ec);
|
||||
int tmp_optlen = static_cast<int>(*optlen);
|
||||
int result = error_wrapper(::getsockopt(s, level, optname,
|
||||
reinterpret_cast<char*>(optval), &tmp_optlen), ec);
|
||||
*optlen = static_cast<size_t>(tmp_optlen);
|
||||
int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
|
||||
s, level, optname, optval, optlen), ec);
|
||||
if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
|
||||
&& ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
|
||||
{
|
||||
|
@ -409,13 +509,15 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
|||
*static_cast<DWORD*>(optval) = 1;
|
||||
clear_error(ec);
|
||||
}
|
||||
# if defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
clear_error(ec);
|
||||
socklen_t tmp_optlen = static_cast<socklen_t>(*optlen);
|
||||
int result = error_wrapper(::getsockopt(s, level, optname,
|
||||
optval, &tmp_optlen), ec);
|
||||
*optlen = static_cast<size_t>(tmp_optlen);
|
||||
int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
|
||||
s, level, optname, optval, optlen), ec);
|
||||
#if defined(__linux__)
|
||||
if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
|
||||
&& (optname == SO_SNDBUF || optname == SO_RCVBUF))
|
||||
|
@ -432,18 +534,50 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
|||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_getpeername(SockLenType msghdr::*,
|
||||
socket_type s, socket_addr_type* addr, std::size_t* addrlen)
|
||||
{
|
||||
SockLenType tmp_addrlen = (SockLenType)*addrlen;
|
||||
int result = ::getpeername(s, addr, &tmp_addrlen);
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getpeername(socket_type s, socket_addr_type* addr,
|
||||
socket_addr_len_type* addrlen, asio::error_code& ec)
|
||||
std::size_t* addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::getpeername(s, addr, addrlen), ec);
|
||||
int result = error_wrapper(call_getpeername(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_getsockname(SockLenType msghdr::*,
|
||||
socket_type s, socket_addr_type* addr, std::size_t* addrlen)
|
||||
{
|
||||
SockLenType tmp_addrlen = (SockLenType)*addrlen;
|
||||
int result = ::getsockname(s, addr, &tmp_addrlen);
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getsockname(socket_type s, socket_addr_type* addr,
|
||||
socket_addr_len_type* addrlen, asio::error_code& ec)
|
||||
std::size_t* addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::getsockname(s, addr, addrlen), ec);
|
||||
int result = error_wrapper(call_getsockname(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
|
||||
|
@ -451,7 +585,12 @@ inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
|
|||
{
|
||||
clear_error(ec);
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(::ioctlsocket(s, cmd, arg), ec);
|
||||
int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(::ioctl(s, cmd, arg), ec);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
@ -482,8 +621,22 @@ inline int select(int nfds, fd_set* readfds, fd_set* writefds,
|
|||
&& timeout->tv_usec > 0 && timeout->tv_usec < 1000)
|
||||
timeout->tv_usec = 1000;
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(::select(nfds, readfds,
|
||||
|
||||
#if defined(__hpux) && defined(__HP_aCC)
|
||||
timespec ts;
|
||||
ts.tv_sec = timeout ? timeout->tv_sec : 0;
|
||||
ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
|
||||
return error_wrapper(::pselect(nfds, readfds,
|
||||
writefds, exceptfds, timeout ? &ts : 0, 0), ec);
|
||||
#else
|
||||
int result = error_wrapper(::select(nfds, readfds,
|
||||
writefds, exceptfds, timeout), ec);
|
||||
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int poll_read(socket_type s, asio::error_code& ec)
|
||||
|
@ -493,7 +646,12 @@ inline int poll_read(socket_type s, asio::error_code& ec)
|
|||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
clear_error(ec);
|
||||
return error_wrapper(::select(s, &fds, 0, 0, 0), ec);
|
||||
int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
pollfd fds;
|
||||
fds.fd = s;
|
||||
|
@ -511,7 +669,12 @@ inline int poll_write(socket_type s, asio::error_code& ec)
|
|||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
clear_error(ec);
|
||||
return error_wrapper(::select(s, 0, &fds, 0, 0), ec);
|
||||
int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
pollfd fds;
|
||||
fds.fd = s;
|
||||
|
@ -559,9 +722,17 @@ inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
|
|||
}
|
||||
|
||||
DWORD string_length = static_cast<DWORD>(length);
|
||||
#if defined(BOOST_NO_ANSI_APIS)
|
||||
LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
|
||||
int result = error_wrapper(::WSAAddressToStringW(
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
address_length, 0, string_buffer, &string_length), ec);
|
||||
::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
|
||||
#else
|
||||
int result = error_wrapper(::WSAAddressToStringA(
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
address_length, 0, dest, &string_length), ec);
|
||||
#endif
|
||||
|
||||
// Windows may set error code on success.
|
||||
if (result != socket_error_retval)
|
||||
|
@ -605,10 +776,20 @@ inline int inet_pton(int af, const char* src, void* dest,
|
|||
|
||||
sockaddr_storage_type address;
|
||||
int address_length = sizeof(sockaddr_storage_type);
|
||||
#if defined(BOOST_NO_ANSI_APIS)
|
||||
int num_wide_chars = strlen(src) + 1;
|
||||
LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
|
||||
::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
|
||||
int result = error_wrapper(::WSAStringToAddressW(
|
||||
wide_buffer, af, 0,
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
&address_length), ec);
|
||||
#else
|
||||
int result = error_wrapper(::WSAStringToAddressA(
|
||||
const_cast<char*>(src), af, 0,
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
&address_length), ec);
|
||||
#endif
|
||||
|
||||
if (af == AF_INET)
|
||||
{
|
||||
|
@ -642,6 +823,11 @@ inline int inet_pton(int af, const char* src, void* dest,
|
|||
if (result == socket_error_retval && !ec)
|
||||
ec = asio::error::invalid_argument;
|
||||
|
||||
#if defined(UNDER_CE)
|
||||
if (result != socket_error_retval)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
|
||||
return result == socket_error_retval ? -1 : 1;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
int result = error_wrapper(::inet_pton(af, src, dest), ec);
|
||||
|
@ -668,7 +854,12 @@ inline int inet_pton(int af, const char* src, void* dest,
|
|||
inline int gethostname(char* name, int namelen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::gethostname(name, namelen), ec);
|
||||
int result = error_wrapper(::gethostname(name, namelen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
|
||||
|
@ -707,6 +898,9 @@ inline hostent* gethostbyaddr(const char* addr, int length, int af,
|
|||
hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
|
||||
if (!retval)
|
||||
return 0;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
*result = *retval;
|
||||
return retval;
|
||||
#elif defined(__sun) || defined(__QNX__)
|
||||
|
@ -755,6 +949,9 @@ inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
|
|||
hostent* retval = error_wrapper(::gethostbyname(name), ec);
|
||||
if (!retval)
|
||||
return 0;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
*result = *retval;
|
||||
return result;
|
||||
#elif defined(__sun) || defined(__QNX__)
|
||||
|
@ -1373,7 +1570,7 @@ inline int getaddrinfo_emulation(const char* host, const char* service,
|
|||
}
|
||||
|
||||
inline asio::error_code getnameinfo_emulation(
|
||||
const socket_addr_type* sa, socket_addr_len_type salen, char* host,
|
||||
const socket_addr_type* sa, std::size_t salen, char* host,
|
||||
std::size_t hostlen, char* serv, std::size_t servlen, int flags,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
|
@ -1526,10 +1723,10 @@ inline asio::error_code translate_addrinfo_error(int error)
|
|||
default: // Possibly the non-portable EAI_SYSTEM.
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return asio::error_code(
|
||||
WSAGetLastError(), asio::error::system_category);
|
||||
WSAGetLastError(), asio::error::get_system_category());
|
||||
#else
|
||||
return asio::error_code(
|
||||
errno, asio::error::system_category);
|
||||
errno, asio::error::get_system_category());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1540,7 +1737,7 @@ inline asio::error_code getaddrinfo(const char* host,
|
|||
{
|
||||
clear_error(ec);
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
|
||||
// Building for Windows XP, Windows Server 2003, or later.
|
||||
int error = ::getaddrinfo(host, service, hints, result);
|
||||
return ec = translate_addrinfo_error(error);
|
||||
|
@ -1571,7 +1768,7 @@ inline asio::error_code getaddrinfo(const char* host,
|
|||
inline void freeaddrinfo(addrinfo_type* ai)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
|
||||
// Building for Windows XP, Windows Server 2003, or later.
|
||||
::freeaddrinfo(ai);
|
||||
# else
|
||||
|
@ -1595,11 +1792,11 @@ inline void freeaddrinfo(addrinfo_type* ai)
|
|||
}
|
||||
|
||||
inline asio::error_code getnameinfo(const socket_addr_type* addr,
|
||||
socket_addr_len_type addrlen, char* host, std::size_t hostlen,
|
||||
std::size_t addrlen, char* host, std::size_t hostlen,
|
||||
char* serv, std::size_t servlen, int flags, asio::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
|
||||
// Building for Windows XP, Windows Server 2003, or later.
|
||||
clear_error(ec);
|
||||
int error = ::getnameinfo(addr, addrlen, host, static_cast<DWORD>(hostlen),
|
||||
|
@ -1608,7 +1805,7 @@ inline asio::error_code getnameinfo(const socket_addr_type* addr,
|
|||
# else
|
||||
// Building for Windows 2000 or earlier.
|
||||
typedef int (WSAAPI *gni_t)(const socket_addr_type*,
|
||||
socket_addr_len_type, char*, std::size_t, char*, std::size_t, int);
|
||||
int, char*, std::size_t, char*, std::size_t, int);
|
||||
if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
|
||||
{
|
||||
if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
using namespace std; // For memset.
|
||||
sockaddr_in4_type addr;
|
||||
socket_addr_len_type addr_len = sizeof(addr);
|
||||
std::size_t addr_len = sizeof(addr);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
|
|
@ -29,12 +29,12 @@
|
|||
# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
|
||||
# if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately")
|
||||
# pragma message("Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target)")
|
||||
# pragma message("Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)")
|
||||
# else // defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately
|
||||
# warning Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target)
|
||||
# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)
|
||||
# endif // defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
|
||||
# if defined(_MSC_VER)
|
||||
# if defined(_WIN32) && !defined(WIN32)
|
||||
|
@ -80,7 +80,9 @@
|
|||
# undef ASIO_WSPIAPI_H_DEFINED
|
||||
# endif // defined(ASIO_WSPIAPI_H_DEFINED)
|
||||
# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
|
||||
# if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# if defined(UNDER_CE)
|
||||
# pragma comment(lib, "ws2.lib")
|
||||
# elif defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# pragma comment(lib, "ws2_32.lib")
|
||||
# pragma comment(lib, "mswsock.lib")
|
||||
# endif // defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
|
@ -116,7 +118,6 @@ const int socket_error_retval = SOCKET_ERROR;
|
|||
const int max_addr_v4_str_len = 256;
|
||||
const int max_addr_v6_str_len = 256;
|
||||
typedef sockaddr socket_addr_type;
|
||||
typedef int socket_addr_len_type;
|
||||
typedef in_addr in4_addr_type;
|
||||
typedef ip_mreq in4_mreq_type;
|
||||
typedef sockaddr_in sockaddr_in4_type;
|
||||
|
@ -154,7 +155,6 @@ const int socket_error_retval = -1;
|
|||
const int max_addr_v4_str_len = INET_ADDRSTRLEN;
|
||||
const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
|
||||
typedef sockaddr socket_addr_type;
|
||||
typedef socklen_t socket_addr_len_type;
|
||||
typedef in_addr in4_addr_type;
|
||||
typedef ip_mreq in4_mreq_type;
|
||||
typedef sockaddr_in sockaddr_in4_type;
|
||||
|
|
|
@ -135,9 +135,9 @@ public:
|
|||
handler_base* last_waiter_;
|
||||
|
||||
// Storage for posted handlers.
|
||||
typedef boost::aligned_storage<64> handler_storage_type;
|
||||
typedef boost::aligned_storage<128> handler_storage_type;
|
||||
#if defined(__BORLANDC__)
|
||||
boost::aligned_storage<64> handler_storage_;
|
||||
boost::aligned_storage<128> handler_storage_;
|
||||
#else
|
||||
handler_storage_type handler_storage_;
|
||||
#endif
|
||||
|
@ -235,7 +235,7 @@ public:
|
|||
void* do_handler_allocate(std::size_t size)
|
||||
{
|
||||
#if defined(__BORLANDC__)
|
||||
BOOST_ASSERT(size <= boost::aligned_storage<64>::size);
|
||||
BOOST_ASSERT(size <= boost::aligned_storage<128>::size);
|
||||
#else
|
||||
BOOST_ASSERT(size <= strand_impl::handler_storage_type::size);
|
||||
#endif
|
||||
|
@ -276,7 +276,7 @@ public:
|
|||
if (impl_->first_waiter_ == 0)
|
||||
impl_->last_waiter_ = 0;
|
||||
lock.unlock();
|
||||
service_impl_.io_service().post(
|
||||
service_impl_.get_io_service().post(
|
||||
invoke_current_handler(service_impl_, impl_));
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ public:
|
|||
// This handler now has the lock, so can be dispatched immediately.
|
||||
impl->current_handler_ = ptr.get();
|
||||
lock.unlock();
|
||||
this->io_service().dispatch(invoke_current_handler(*this, impl));
|
||||
this->get_io_service().dispatch(invoke_current_handler(*this, impl));
|
||||
ptr.release();
|
||||
}
|
||||
else
|
||||
|
@ -469,7 +469,7 @@ public:
|
|||
// This handler now has the lock, so can be dispatched immediately.
|
||||
impl->current_handler_ = ptr.get();
|
||||
lock.unlock();
|
||||
this->io_service().post(invoke_current_handler(*this, impl));
|
||||
this->get_io_service().post(invoke_current_handler(*this, impl));
|
||||
ptr.release();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "asio/detail/event.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/handler_queue.hpp"
|
||||
#include "asio/detail/mutex.hpp"
|
||||
#include "asio/detail/service_base.hpp"
|
||||
#include "asio/detail/task_io_service_fwd.hpp"
|
||||
|
@ -42,12 +43,11 @@ public:
|
|||
task_(use_service<Task>(io_service)),
|
||||
task_interrupted_(true),
|
||||
outstanding_work_(0),
|
||||
handler_queue_(&task_handler_),
|
||||
handler_queue_end_(&task_handler_),
|
||||
stopped_(false),
|
||||
shutdown_(false),
|
||||
first_idle_thread_(0)
|
||||
{
|
||||
handler_queue_.push(&task_handler_);
|
||||
}
|
||||
|
||||
void init(size_t /*concurrency_hint*/)
|
||||
|
@ -62,17 +62,16 @@ public:
|
|||
lock.unlock();
|
||||
|
||||
// Destroy handler objects.
|
||||
while (handler_queue_)
|
||||
while (!handler_queue_.empty())
|
||||
{
|
||||
handler_base* h = handler_queue_;
|
||||
handler_queue_ = h->next_;
|
||||
handler_queue::handler* h = handler_queue_.front();
|
||||
handler_queue_.pop();
|
||||
if (h != &task_handler_)
|
||||
h->destroy();
|
||||
}
|
||||
|
||||
// Reset handler queue to initial state.
|
||||
handler_queue_ = &task_handler_;
|
||||
handler_queue_end_ = &task_handler_;
|
||||
handler_queue_.push(&task_handler_);
|
||||
}
|
||||
|
||||
// Run the event loop until interrupted or no more work.
|
||||
|
@ -173,10 +172,7 @@ public:
|
|||
void post(Handler handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef handler_wrapper<Handler> value_type;
|
||||
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
|
||||
raw_handler_ptr<alloc_traits> raw_ptr(handler);
|
||||
handler_ptr<alloc_traits> ptr(raw_ptr, handler);
|
||||
handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
|
||||
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
|
@ -185,15 +181,7 @@ public:
|
|||
return;
|
||||
|
||||
// Add the handler to the end of the queue.
|
||||
if (handler_queue_end_)
|
||||
{
|
||||
handler_queue_end_->next_ = ptr.get();
|
||||
handler_queue_end_ = ptr.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
handler_queue_ = handler_queue_end_ = ptr.get();
|
||||
}
|
||||
handler_queue_.push(ptr.get());
|
||||
ptr.release();
|
||||
|
||||
// An undelivered handler is treated as unfinished work.
|
||||
|
@ -227,29 +215,28 @@ private:
|
|||
bool task_has_run = false;
|
||||
while (!stopped_)
|
||||
{
|
||||
if (handler_queue_)
|
||||
if (!handler_queue_.empty())
|
||||
{
|
||||
// Prepare to execute first handler from queue.
|
||||
handler_base* h = handler_queue_;
|
||||
handler_queue_ = h->next_;
|
||||
if (handler_queue_ == 0)
|
||||
handler_queue_end_ = 0;
|
||||
h->next_ = 0;
|
||||
handler_queue::handler* h = handler_queue_.front();
|
||||
handler_queue_.pop();
|
||||
|
||||
if (h == &task_handler_)
|
||||
{
|
||||
bool more_handlers = (handler_queue_ != 0);
|
||||
bool more_handlers = (!handler_queue_.empty());
|
||||
task_interrupted_ = more_handlers || polling;
|
||||
lock.unlock();
|
||||
|
||||
// If the task has already run and we're polling then we're done.
|
||||
if (task_has_run && polling)
|
||||
{
|
||||
task_interrupted_ = true;
|
||||
handler_queue_.push(&task_handler_);
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
task_has_run = true;
|
||||
|
||||
|
||||
lock.unlock();
|
||||
task_cleanup c(lock, *this);
|
||||
|
||||
// Run the task. May throw an exception. Only block if the handler
|
||||
|
@ -263,7 +250,7 @@ private:
|
|||
handler_cleanup c(lock, *this);
|
||||
|
||||
// Invoke the handler. May throw an exception.
|
||||
h->call(); // call() deletes the handler object
|
||||
h->invoke(); // invoke() deletes the handler object
|
||||
|
||||
ec = asio::error_code();
|
||||
return 1;
|
||||
|
@ -330,94 +317,9 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Helper class to perform task-related operations on block exit.
|
||||
class task_cleanup;
|
||||
friend class task_cleanup;
|
||||
|
||||
// The base class for all handler wrappers. A function pointer is used
|
||||
// instead of virtual functions to avoid the associated overhead.
|
||||
class handler_base
|
||||
{
|
||||
public:
|
||||
typedef void (*call_func_type)(handler_base*);
|
||||
typedef void (*destroy_func_type)(handler_base*);
|
||||
|
||||
handler_base(call_func_type call_func, destroy_func_type destroy_func)
|
||||
: next_(0),
|
||||
call_func_(call_func),
|
||||
destroy_func_(destroy_func)
|
||||
{
|
||||
}
|
||||
|
||||
void call()
|
||||
{
|
||||
call_func_(this);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
destroy_func_(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Prevent deletion through this type.
|
||||
~handler_base()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class task_io_service<Task>;
|
||||
friend class task_cleanup;
|
||||
handler_base* next_;
|
||||
call_func_type call_func_;
|
||||
destroy_func_type destroy_func_;
|
||||
};
|
||||
|
||||
// Template wrapper for handlers.
|
||||
template <typename Handler>
|
||||
class handler_wrapper
|
||||
: public handler_base
|
||||
{
|
||||
public:
|
||||
handler_wrapper(Handler handler)
|
||||
: handler_base(&handler_wrapper<Handler>::do_call,
|
||||
&handler_wrapper<Handler>::do_destroy),
|
||||
handler_(handler)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_call(handler_base* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made.
|
||||
Handler handler(h->handler_);
|
||||
|
||||
// Free the memory associated with the handler.
|
||||
ptr.reset();
|
||||
|
||||
// Make the upcall.
|
||||
asio_handler_invoke_helpers::invoke(handler, &handler);
|
||||
}
|
||||
|
||||
static void do_destroy(handler_base* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
// Helper class to perform task-related operations on block exit.
|
||||
class task_cleanup
|
||||
{
|
||||
public:
|
||||
|
@ -433,20 +335,7 @@ private:
|
|||
// Reinsert the task at the end of the handler queue.
|
||||
lock_.lock();
|
||||
task_io_service_.task_interrupted_ = true;
|
||||
task_io_service_.task_handler_.next_ = 0;
|
||||
if (task_io_service_.handler_queue_end_)
|
||||
{
|
||||
task_io_service_.handler_queue_end_->next_
|
||||
= &task_io_service_.task_handler_;
|
||||
task_io_service_.handler_queue_end_
|
||||
= &task_io_service_.task_handler_;
|
||||
}
|
||||
else
|
||||
{
|
||||
task_io_service_.handler_queue_
|
||||
= task_io_service_.handler_queue_end_
|
||||
= &task_io_service_.task_handler_;
|
||||
}
|
||||
task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -487,11 +376,11 @@ private:
|
|||
|
||||
// Handler object to represent the position of the task in the queue.
|
||||
class task_handler
|
||||
: public handler_base
|
||||
: public handler_queue::handler
|
||||
{
|
||||
public:
|
||||
task_handler()
|
||||
: handler_base(0, 0)
|
||||
: handler_queue::handler(0, 0)
|
||||
{
|
||||
}
|
||||
} task_handler_;
|
||||
|
@ -502,11 +391,8 @@ private:
|
|||
// The count of unfinished work.
|
||||
int outstanding_work_;
|
||||
|
||||
// The start of a linked list of handlers that are ready to be delivered.
|
||||
handler_base* handler_queue_;
|
||||
|
||||
// The end of a linked list of handlers that are ready to be delivered.
|
||||
handler_base* handler_queue_end_;
|
||||
// The queue of handlers that are ready to be delivered.
|
||||
handler_queue handler_queue_;
|
||||
|
||||
// Flag to indicate that the dispatcher has been stopped.
|
||||
bool stopped_;
|
||||
|
|
|
@ -24,7 +24,11 @@
|
|||
#if !defined(BOOST_HAS_THREADS)
|
||||
# include "asio/detail/null_thread.hpp"
|
||||
#elif defined(BOOST_WINDOWS)
|
||||
# include "asio/detail/win_thread.hpp"
|
||||
# if defined(UNDER_CE)
|
||||
# include "asio/detail/wince_thread.hpp"
|
||||
# else
|
||||
# include "asio/detail/win_thread.hpp"
|
||||
# endif
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
# include "asio/detail/posix_thread.hpp"
|
||||
#else
|
||||
|
@ -37,7 +41,11 @@ namespace detail {
|
|||
#if !defined(BOOST_HAS_THREADS)
|
||||
typedef null_thread thread;
|
||||
#elif defined(BOOST_WINDOWS)
|
||||
# if defined(UNDER_CE)
|
||||
typedef wince_thread thread;
|
||||
# else
|
||||
typedef win_thread thread;
|
||||
# endif
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
typedef posix_thread thread;
|
||||
#endif
|
||||
|
|
|
@ -162,13 +162,7 @@ public:
|
|||
// Destroy timers that are waiting to be cleaned up.
|
||||
virtual void cleanup_timers()
|
||||
{
|
||||
while (cleanup_timers_)
|
||||
{
|
||||
timer_base* next_timer = cleanup_timers_->next_;
|
||||
cleanup_timers_->next_ = 0;
|
||||
cleanup_timers_->destroy();
|
||||
cleanup_timers_ = next_timer;
|
||||
}
|
||||
destroy_timer_list(cleanup_timers_);
|
||||
}
|
||||
|
||||
// Destroy all timers.
|
||||
|
@ -181,11 +175,12 @@ public:
|
|||
timer_base* t = i->second;
|
||||
typename hash_map<void*, timer_base*>::iterator old_i = i++;
|
||||
timers_.erase(old_i);
|
||||
t->destroy();
|
||||
destroy_timer_list(t);
|
||||
}
|
||||
heap_.clear();
|
||||
timers_.clear();
|
||||
cleanup_timers();
|
||||
destroy_timer_list(cancelled_timers_);
|
||||
destroy_timer_list(cleanup_timers_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -367,6 +362,18 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Destroy all timers in a linked list.
|
||||
void destroy_timer_list(timer_base*& t)
|
||||
{
|
||||
while (t)
|
||||
{
|
||||
timer_base* next = t->next_;
|
||||
t->next_ = 0;
|
||||
t->destroy();
|
||||
t = next;
|
||||
}
|
||||
}
|
||||
|
||||
// A hash of timer token to linked lists of timers.
|
||||
hash_map<void*, timer_base*> timers_;
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"event");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/service_base.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
#include "asio/detail/timer_queue.hpp"
|
||||
#include "asio/detail/win_iocp_operation.hpp"
|
||||
#include "asio/detail/mutex.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
@ -51,7 +53,9 @@ public:
|
|||
iocp_(),
|
||||
outstanding_work_(0),
|
||||
stopped_(0),
|
||||
shutdown_(0)
|
||||
shutdown_(0),
|
||||
timer_thread_(0),
|
||||
timer_interrupt_issued_(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -64,7 +68,7 @@ public:
|
|||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"iocp");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
@ -93,6 +97,10 @@ public:
|
|||
if (overlapped)
|
||||
static_cast<operation*>(overlapped)->destroy();
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
timer_queues_[i]->destroy_timers();
|
||||
timer_queues_.clear();
|
||||
}
|
||||
|
||||
// Register a handle with the IO completion port.
|
||||
|
@ -175,7 +183,7 @@ public:
|
|||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"pqcs");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
@ -231,7 +239,7 @@ public:
|
|||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"pqcs");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
@ -251,20 +259,102 @@ public:
|
|||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"pqcs");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new timer queue to the service.
|
||||
template <typename Time_Traits>
|
||||
void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(timer_mutex_);
|
||||
timer_queues_.push_back(&timer_queue);
|
||||
}
|
||||
|
||||
// Remove a timer queue from the service.
|
||||
template <typename Time_Traits>
|
||||
void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(timer_mutex_);
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
{
|
||||
if (timer_queues_[i] == &timer_queue)
|
||||
{
|
||||
timer_queues_.erase(timer_queues_.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule a timer in the given timer queue to expire at the specified
|
||||
// absolute time. The handler object will be invoked when the timer expires.
|
||||
template <typename Time_Traits, typename Handler>
|
||||
void schedule_timer(timer_queue<Time_Traits>& timer_queue,
|
||||
const typename Time_Traits::time_type& time, Handler handler, void* token)
|
||||
{
|
||||
// If the service has been shut down we silently discard the timer.
|
||||
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
|
||||
return;
|
||||
|
||||
asio::detail::mutex::scoped_lock lock(timer_mutex_);
|
||||
if (timer_queue.enqueue_timer(time, handler, token))
|
||||
{
|
||||
if (!timer_interrupt_issued_)
|
||||
{
|
||||
timer_interrupt_issued_ = true;
|
||||
lock.unlock();
|
||||
::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, steal_timer_dispatching, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the timer associated with the given token. Returns the number of
|
||||
// handlers that have been posted or dispatched.
|
||||
template <typename Time_Traits>
|
||||
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
|
||||
{
|
||||
// If the service has been shut down we silently ignore the cancellation.
|
||||
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
|
||||
return 0;
|
||||
|
||||
asio::detail::mutex::scoped_lock lock(timer_mutex_);
|
||||
std::size_t n = timer_queue.cancel_timer(token);
|
||||
if (n > 0 && !timer_interrupt_issued_)
|
||||
{
|
||||
timer_interrupt_issued_ = true;
|
||||
lock.unlock();
|
||||
::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, steal_timer_dispatching, 0);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
private:
|
||||
// Dequeues at most one operation from the I/O completion port, and then
|
||||
// executes it. Returns the number of operations that were dequeued (i.e.
|
||||
// either 0 or 1).
|
||||
size_t do_one(bool block, asio::error_code& ec)
|
||||
{
|
||||
long this_thread_id = static_cast<long>(::GetCurrentThreadId());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Try to acquire responsibility for dispatching timers.
|
||||
bool dispatching_timers = (::InterlockedCompareExchange(
|
||||
&timer_thread_, this_thread_id, 0) == 0);
|
||||
|
||||
// Calculate timeout for GetQueuedCompletionStatus call.
|
||||
DWORD timeout = max_timeout;
|
||||
if (dispatching_timers)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(timer_mutex_);
|
||||
timer_interrupt_issued_ = false;
|
||||
timeout = get_timeout();
|
||||
}
|
||||
|
||||
// Get the next operation from the queue.
|
||||
DWORD bytes_transferred = 0;
|
||||
#if (WINVER < 0x0500)
|
||||
|
@ -275,18 +365,47 @@ private:
|
|||
LPOVERLAPPED overlapped = 0;
|
||||
::SetLastError(0);
|
||||
BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
|
||||
&completion_key, &overlapped, block ? 1000 : 0);
|
||||
&completion_key, &overlapped, block ? timeout : 0);
|
||||
DWORD last_error = ::GetLastError();
|
||||
|
||||
// Dispatch any pending timers.
|
||||
if (dispatching_timers)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(timer_mutex_);
|
||||
timer_queues_copy_ = timer_queues_;
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
{
|
||||
timer_queues_[i]->dispatch_timers();
|
||||
timer_queues_[i]->dispatch_cancellations();
|
||||
timer_queues_[i]->cleanup_timers();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok && overlapped == 0)
|
||||
{
|
||||
if (block && last_error == WAIT_TIMEOUT)
|
||||
{
|
||||
// Relinquish responsibility for dispatching timers.
|
||||
if (dispatching_timers)
|
||||
{
|
||||
::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Transfer responsibility for dispatching timers to another thread.
|
||||
if (dispatching_timers && ::InterlockedCompareExchange(
|
||||
&timer_thread_, 0, this_thread_id) == this_thread_id)
|
||||
{
|
||||
::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, transfer_timer_dispatching, 0);
|
||||
}
|
||||
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (overlapped)
|
||||
else if (overlapped)
|
||||
{
|
||||
// We may have been passed a last_error value in the completion_key.
|
||||
if (last_error == 0)
|
||||
|
@ -294,6 +413,14 @@ private:
|
|||
last_error = completion_key;
|
||||
}
|
||||
|
||||
// Transfer responsibility for dispatching timers to another thread.
|
||||
if (dispatching_timers && ::InterlockedCompareExchange(
|
||||
&timer_thread_, 0, this_thread_id) == this_thread_id)
|
||||
{
|
||||
::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, transfer_timer_dispatching, 0);
|
||||
}
|
||||
|
||||
// Ensure that the io_service does not exit due to running out of work
|
||||
// while we make the upcall.
|
||||
auto_work work(*this);
|
||||
|
@ -305,18 +432,34 @@ private:
|
|||
ec = asio::error_code();
|
||||
return 1;
|
||||
}
|
||||
else if (completion_key == transfer_timer_dispatching)
|
||||
{
|
||||
// Woken up to try to acquire responsibility for dispatching timers.
|
||||
::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
|
||||
}
|
||||
else if (completion_key == steal_timer_dispatching)
|
||||
{
|
||||
// Woken up to steal responsibility for dispatching timers.
|
||||
::InterlockedExchange(&timer_thread_, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The stopped_ flag is always checked to ensure that any leftover
|
||||
// interrupts from a previous run invocation are ignored.
|
||||
if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
|
||||
{
|
||||
// Relinquish responsibility for dispatching timers.
|
||||
if (dispatching_timers)
|
||||
{
|
||||
::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
|
||||
}
|
||||
|
||||
// Wake up next thread that is blocked on GetQueuedCompletionStatus.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -327,6 +470,45 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Check if all timer queues are empty.
|
||||
bool all_timer_queues_are_empty() const
|
||||
{
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
if (!timer_queues_[i]->empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the timeout value for the GetQueuedCompletionStatus call. The timeout
|
||||
// value is returned as a number of milliseconds. We will wait no longer than
|
||||
// 1000 milliseconds.
|
||||
DWORD get_timeout()
|
||||
{
|
||||
if (all_timer_queues_are_empty())
|
||||
return max_timeout;
|
||||
|
||||
boost::posix_time::time_duration minimum_wait_duration
|
||||
= boost::posix_time::milliseconds(max_timeout);
|
||||
|
||||
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
|
||||
{
|
||||
boost::posix_time::time_duration wait_duration
|
||||
= timer_queues_[i]->wait_duration();
|
||||
if (wait_duration < minimum_wait_duration)
|
||||
minimum_wait_duration = wait_duration;
|
||||
}
|
||||
|
||||
if (minimum_wait_duration > boost::posix_time::time_duration())
|
||||
{
|
||||
int milliseconds = minimum_wait_duration.total_milliseconds();
|
||||
return static_cast<DWORD>(milliseconds > 0 ? milliseconds : 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct auto_work
|
||||
{
|
||||
auto_work(win_iocp_io_service& io_service)
|
||||
|
@ -416,6 +598,37 @@ private:
|
|||
|
||||
// Flag to indicate whether the service has been shut down.
|
||||
long shutdown_;
|
||||
|
||||
enum
|
||||
{
|
||||
// Maximum GetQueuedCompletionStatus timeout, in milliseconds.
|
||||
max_timeout = 1000,
|
||||
|
||||
// Completion key value to indicate that responsibility for dispatching
|
||||
// timers is being cooperatively transferred from one thread to another.
|
||||
transfer_timer_dispatching = 1,
|
||||
|
||||
// Completion key value to indicate that responsibility for dispatching
|
||||
// timers should be stolen from another thread.
|
||||
steal_timer_dispatching = 2
|
||||
};
|
||||
|
||||
// The thread that's currently in charge of dispatching timers.
|
||||
long timer_thread_;
|
||||
|
||||
// Mutex for protecting access to the timer queues.
|
||||
mutex timer_mutex_;
|
||||
|
||||
// Whether a thread has been interrupted to process a new timeout.
|
||||
bool timer_interrupt_issued_;
|
||||
|
||||
// The timer queues.
|
||||
std::vector<timer_queue_base*> timer_queues_;
|
||||
|
||||
// A copy of the timer queues, used when dispatching, cancelling and cleaning
|
||||
// up timers. The copy is stored as a class data member to avoid unnecessary
|
||||
// memory allocation.
|
||||
std::vector<timer_queue_base*> timer_queues_copy_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#if !defined(ASIO_DISABLE_IOCP)
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
|
||||
#if !defined(UNDER_CE)
|
||||
|
||||
// Define this to indicate that IOCP is supported on the target platform.
|
||||
#define ASIO_HAS_IOCP 1
|
||||
|
@ -39,6 +40,7 @@ class win_iocp_io_service;
|
|||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#endif // !defined(UNDER_CE)
|
||||
#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
#endif // !defined(ASIO_DISABLE_IOCP)
|
||||
|
|
|
@ -327,7 +327,7 @@ public:
|
|||
ec = asio::error::bad_descriptor;
|
||||
}
|
||||
else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
|
||||
::GetModuleHandle("KERNEL32"), "CancelIoEx"))
|
||||
::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
|
||||
{
|
||||
// The version of Windows supports cancellation from any thread.
|
||||
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
|
||||
|
@ -338,7 +338,7 @@ public:
|
|||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -360,7 +360,7 @@ public:
|
|||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -561,7 +561,7 @@ public:
|
|||
}
|
||||
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
|
@ -600,7 +600,7 @@ public:
|
|||
else
|
||||
{
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
|
@ -667,7 +667,7 @@ public:
|
|||
else if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -719,7 +719,7 @@ public:
|
|||
|
||||
// Map non-portable errors to their portable counterparts.
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
if (ec.value() == ERROR_NETNAME_DELETED)
|
||||
{
|
||||
if (handler_op->cancel_token_.expired())
|
||||
|
@ -767,7 +767,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
return;
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ public:
|
|||
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
|
||||
raw_handler_ptr<alloc_traits> raw_ptr(handler);
|
||||
handler_ptr<alloc_traits> ptr(raw_ptr,
|
||||
this->io_service(), impl.cancel_token_, buffers, handler);
|
||||
this->get_io_service(), impl.cancel_token_, buffers, handler);
|
||||
|
||||
// Copy buffers into WSABUF array.
|
||||
::WSABUF bufs[max_buffers];
|
||||
|
@ -803,7 +803,7 @@ public:
|
|||
// A request to receive 0 bytes on a stream socket is a no-op.
|
||||
if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
|
||||
{
|
||||
asio::io_service::work work(this->io_service());
|
||||
asio::io_service::work work(this->get_io_service());
|
||||
ptr.reset();
|
||||
asio::error_code error;
|
||||
iocp_service_.post(bind_handler(handler, error, 0));
|
||||
|
@ -819,10 +819,10 @@ public:
|
|||
// Check if the operation completed immediately.
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
{
|
||||
asio::io_service::work work(this->io_service());
|
||||
asio::io_service::work work(this->get_io_service());
|
||||
ptr.reset();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
|
||||
}
|
||||
else
|
||||
|
@ -867,7 +867,7 @@ public:
|
|||
if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -917,7 +917,7 @@ public:
|
|||
|
||||
// Map non-portable errors to their portable counterparts.
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
if (ec.value() == ERROR_PORT_UNREACHABLE)
|
||||
{
|
||||
ec = asio::error::connection_refused;
|
||||
|
@ -958,7 +958,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
return;
|
||||
}
|
||||
|
@ -974,7 +974,7 @@ public:
|
|||
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
|
||||
raw_handler_ptr<alloc_traits> raw_ptr(handler);
|
||||
handler_ptr<alloc_traits> ptr(raw_ptr,
|
||||
this->io_service(), buffers, handler);
|
||||
this->get_io_service(), buffers, handler);
|
||||
|
||||
// Copy buffers into WSABUF array.
|
||||
::WSABUF bufs[max_buffers];
|
||||
|
@ -998,10 +998,10 @@ public:
|
|||
// Check if the operation completed immediately.
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
{
|
||||
asio::io_service::work work(this->io_service());
|
||||
asio::io_service::work work(this->get_io_service());
|
||||
ptr.reset();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
|
||||
}
|
||||
else
|
||||
|
@ -1056,7 +1056,7 @@ public:
|
|||
else if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
if (bytes_transferred == 0)
|
||||
|
@ -1115,7 +1115,7 @@ public:
|
|||
|
||||
// Map non-portable errors to their portable counterparts.
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
if (ec.value() == ERROR_NETNAME_DELETED)
|
||||
{
|
||||
if (handler_op->cancel_token_.expired())
|
||||
|
@ -1170,7 +1170,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
return;
|
||||
}
|
||||
|
@ -1186,7 +1186,7 @@ public:
|
|||
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
|
||||
raw_handler_ptr<alloc_traits> raw_ptr(handler);
|
||||
handler_ptr<alloc_traits> ptr(raw_ptr,
|
||||
this->io_service(), impl.cancel_token_, buffers, handler);
|
||||
this->get_io_service(), impl.cancel_token_, buffers, handler);
|
||||
|
||||
// Copy buffers into WSABUF array.
|
||||
::WSABUF bufs[max_buffers];
|
||||
|
@ -1205,7 +1205,7 @@ public:
|
|||
// A request to receive 0 bytes on a stream socket is a no-op.
|
||||
if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
|
||||
{
|
||||
asio::io_service::work work(this->io_service());
|
||||
asio::io_service::work work(this->get_io_service());
|
||||
ptr.reset();
|
||||
asio::error_code error;
|
||||
iocp_service_.post(bind_handler(handler, error, 0));
|
||||
|
@ -1220,10 +1220,10 @@ public:
|
|||
DWORD last_error = ::WSAGetLastError();
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
{
|
||||
asio::io_service::work work(this->io_service());
|
||||
asio::io_service::work work(this->get_io_service());
|
||||
ptr.reset();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
|
||||
}
|
||||
else
|
||||
|
@ -1261,7 +1261,7 @@ public:
|
|||
// Receive some data.
|
||||
DWORD bytes_transferred = 0;
|
||||
DWORD recv_flags = flags;
|
||||
int endpoint_size = sender_endpoint.capacity();
|
||||
int endpoint_size = static_cast<int>(sender_endpoint.capacity());
|
||||
int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
|
||||
&recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);
|
||||
if (result != 0)
|
||||
|
@ -1270,7 +1270,7 @@ public:
|
|||
if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
if (bytes_transferred == 0)
|
||||
|
@ -1279,7 +1279,7 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
sender_endpoint.resize(endpoint_size);
|
||||
sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));
|
||||
|
||||
ec = asio::error_code();
|
||||
return bytes_transferred;
|
||||
|
@ -1299,7 +1299,7 @@ public:
|
|||
&receive_from_operation<
|
||||
MutableBufferSequence, Handler>::destroy_impl),
|
||||
endpoint_(endpoint),
|
||||
endpoint_size_(endpoint.capacity()),
|
||||
endpoint_size_(static_cast<int>(endpoint.capacity())),
|
||||
work_(io_service),
|
||||
buffers_(buffers),
|
||||
handler_(handler)
|
||||
|
@ -1337,7 +1337,7 @@ public:
|
|||
|
||||
// Map non-portable errors to their portable counterparts.
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
if (ec.value() == ERROR_PORT_UNREACHABLE)
|
||||
{
|
||||
ec = asio::error::connection_refused;
|
||||
|
@ -1390,7 +1390,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor, 0));
|
||||
return;
|
||||
}
|
||||
|
@ -1406,7 +1406,7 @@ public:
|
|||
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
|
||||
raw_handler_ptr<alloc_traits> raw_ptr(handler);
|
||||
handler_ptr<alloc_traits> ptr(raw_ptr,
|
||||
this->io_service(), sender_endp, buffers, handler);
|
||||
this->get_io_service(), sender_endp, buffers, handler);
|
||||
|
||||
// Copy buffers into WSABUF array.
|
||||
::WSABUF bufs[max_buffers];
|
||||
|
@ -1429,10 +1429,10 @@ public:
|
|||
DWORD last_error = ::WSAGetLastError();
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
{
|
||||
asio::io_service::work work(this->io_service());
|
||||
asio::io_service::work work(this->get_io_service());
|
||||
ptr.reset();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
|
||||
}
|
||||
else
|
||||
|
@ -1463,7 +1463,7 @@ public:
|
|||
{
|
||||
asio::error_code ec;
|
||||
socket_holder new_socket;
|
||||
socket_addr_len_type addr_len = 0;
|
||||
std::size_t addr_len = 0;
|
||||
if (peer_endpoint)
|
||||
{
|
||||
addr_len = peer_endpoint->capacity();
|
||||
|
@ -1517,7 +1517,7 @@ public:
|
|||
peer_(peer),
|
||||
protocol_(protocol),
|
||||
peer_endpoint_(peer_endpoint),
|
||||
work_(io_service.io_service()),
|
||||
work_(io_service.get_io_service()),
|
||||
enable_connection_aborted_(enable_connection_aborted),
|
||||
handler_(handler)
|
||||
{
|
||||
|
@ -1618,7 +1618,8 @@ public:
|
|||
GetAcceptExSockaddrs(handler_op->output_buffer(), 0,
|
||||
handler_op->address_length(), handler_op->address_length(),
|
||||
&local_addr, &local_addr_length, &remote_addr, &remote_addr_length);
|
||||
if (remote_addr_length > peer_endpoint.capacity())
|
||||
if (static_cast<std::size_t>(remote_addr_length)
|
||||
> peer_endpoint.capacity())
|
||||
{
|
||||
last_error = WSAEINVAL;
|
||||
}
|
||||
|
@ -1626,7 +1627,7 @@ public:
|
|||
{
|
||||
using namespace std; // For memcpy.
|
||||
memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
|
||||
peer_endpoint.resize(remote_addr_length);
|
||||
peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1670,7 +1671,7 @@ public:
|
|||
|
||||
// Call the handler.
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
detail::bind_handler(handler, ec), &handler);
|
||||
}
|
||||
|
@ -1705,7 +1706,7 @@ public:
|
|||
// Check whether acceptor has been initialised.
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor));
|
||||
return;
|
||||
}
|
||||
|
@ -1713,7 +1714,7 @@ public:
|
|||
// Check that peer socket has not already been opened.
|
||||
if (peer.is_open())
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::already_open));
|
||||
return;
|
||||
}
|
||||
|
@ -1730,7 +1731,7 @@ public:
|
|||
impl.protocol_.type(), impl.protocol_.protocol(), ec));
|
||||
if (sock.get() == invalid_socket)
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec));
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1768,10 +1769,10 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
asio::io_service::work work(this->io_service());
|
||||
asio::io_service::work work(this->get_io_service());
|
||||
ptr.reset();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
iocp_service_.post(bind_handler(handler, ec));
|
||||
}
|
||||
}
|
||||
|
@ -1848,7 +1849,7 @@ public:
|
|||
if (connect_error)
|
||||
{
|
||||
ec = asio::error_code(connect_error,
|
||||
asio::error::system_category);
|
||||
asio::error::get_system_category());
|
||||
io_service_.post(bind_handler(handler_, ec));
|
||||
return true;
|
||||
}
|
||||
|
@ -1887,7 +1888,7 @@ public:
|
|||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler,
|
||||
this->get_io_service().post(bind_handler(handler,
|
||||
asio::error::bad_descriptor));
|
||||
return;
|
||||
}
|
||||
|
@ -1904,7 +1905,8 @@ public:
|
|||
reinterpret_cast<void**>(&reactor_), 0, 0));
|
||||
if (!reactor)
|
||||
{
|
||||
reactor = &(asio::use_service<reactor_type>(this->io_service()));
|
||||
reactor = &(asio::use_service<reactor_type>(
|
||||
this->get_io_service()));
|
||||
interlocked_exchange_pointer(
|
||||
reinterpret_cast<void**>(&reactor_), reactor);
|
||||
}
|
||||
|
@ -1915,7 +1917,7 @@ public:
|
|||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->io_service().post(bind_handler(handler, ec));
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1932,7 +1934,7 @@ public:
|
|||
|
||||
// The connect operation has finished successfully so we need to post the
|
||||
// handler immediately.
|
||||
this->io_service().post(bind_handler(handler, ec));
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
}
|
||||
else if (ec == asio::error::in_progress
|
||||
|| ec == asio::error::would_block)
|
||||
|
@ -1944,7 +1946,7 @@ public:
|
|||
connect_handler<Handler>(
|
||||
impl.socket_,
|
||||
(impl.flags_ & implementation_type::user_set_non_blocking) != 0,
|
||||
completed, this->io_service(), *reactor, handler));
|
||||
completed, this->get_io_service(), *reactor, handler));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1957,7 +1959,7 @@ public:
|
|||
}
|
||||
|
||||
// The connect operation has failed, so post the handler immediately.
|
||||
this->io_service().post(bind_handler(handler, ec));
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// win_local_free_on_block_exit.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 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 ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP
|
||||
#define ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class win_local_free_on_block_exit
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// Constructor blocks all signals for the calling thread.
|
||||
explicit win_local_free_on_block_exit(void* p)
|
||||
: p_(p)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor restores the previous signal mask.
|
||||
~win_local_free_on_block_exit()
|
||||
{
|
||||
::LocalFree(p_);
|
||||
}
|
||||
|
||||
private:
|
||||
void* p_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP
|
|
@ -49,7 +49,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"mutex");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
@ -68,7 +69,8 @@ public:
|
|||
if (error != 0)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(error, asio::error::system_category),
|
||||
asio::error_code(error,
|
||||
asio::error::get_system_category()),
|
||||
"mutex");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
#if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/system_error.hpp"
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"thread");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ inline unsigned int __stdcall win_thread_function(void* arg)
|
|||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
|
|
|
@ -40,16 +40,22 @@ class win_tss_ptr
|
|||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
#if defined(UNDER_CE)
|
||||
enum { out_of_indexes = 0xFFFFFFFF };
|
||||
#else
|
||||
enum { out_of_indexes = TLS_OUT_OF_INDEXES };
|
||||
#endif
|
||||
|
||||
// Constructor.
|
||||
win_tss_ptr()
|
||||
{
|
||||
tss_key_ = ::TlsAlloc();
|
||||
if (tss_key_ == TLS_OUT_OF_INDEXES)
|
||||
if (tss_key_ == out_of_indexes)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"tss");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
//
|
||||
// wince_thread.hpp
|
||||
// ~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2007 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 ASIO_DETAIL_WINCE_THREAD_HPP
|
||||
#define ASIO_DETAIL_WINCE_THREAD_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/system_error.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <memory>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
DWORD WINAPI wince_thread_function(LPVOID arg);
|
||||
|
||||
class wince_thread
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
template <typename Function>
|
||||
wince_thread(Function f)
|
||||
{
|
||||
std::auto_ptr<func_base> arg(new func<Function>(f));
|
||||
DWORD thread_id = 0;
|
||||
thread_ = ::CreateThread(0, 0, wince_thread_function,
|
||||
arg.get(), 0, &thread_id);
|
||||
if (!thread_)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::get_system_category()),
|
||||
"thread");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
arg.release();
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~wince_thread()
|
||||
{
|
||||
::CloseHandle(thread_);
|
||||
}
|
||||
|
||||
// Wait for the thread to exit.
|
||||
void join()
|
||||
{
|
||||
::WaitForSingleObject(thread_, INFINITE);
|
||||
}
|
||||
|
||||
private:
|
||||
friend DWORD WINAPI wince_thread_function(LPVOID arg);
|
||||
|
||||
class func_base
|
||||
{
|
||||
public:
|
||||
virtual ~func_base() {}
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
template <typename Function>
|
||||
class func
|
||||
: public func_base
|
||||
{
|
||||
public:
|
||||
func(Function f)
|
||||
: f_(f)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void run()
|
||||
{
|
||||
f_();
|
||||
}
|
||||
|
||||
private:
|
||||
Function f_;
|
||||
};
|
||||
|
||||
::HANDLE thread_;
|
||||
};
|
||||
|
||||
inline DWORD WINAPI wince_thread_function(LPVOID arg)
|
||||
{
|
||||
std::auto_ptr<wince_thread::func_base> func(
|
||||
static_cast<wince_thread::func_base*>(arg));
|
||||
func->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_WINCE_THREAD_HPP
|
|
@ -28,6 +28,7 @@
|
|||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/system_error.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
@ -86,7 +87,7 @@ public:
|
|||
{
|
||||
asio::system_error e(
|
||||
asio::error_code(ref_->result(),
|
||||
asio::error::system_category),
|
||||
asio::error::get_system_category()),
|
||||
"winsock");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
|
|
@ -197,26 +197,40 @@ enum misc_errors
|
|||
not_found
|
||||
};
|
||||
|
||||
enum ssl_errors
|
||||
{
|
||||
};
|
||||
|
||||
// boostify: error category definitions go here.
|
||||
|
||||
inline asio::error_code make_error_code(basic_errors e)
|
||||
{
|
||||
return asio::error_code(static_cast<int>(e), system_category);
|
||||
return asio::error_code(
|
||||
static_cast<int>(e), get_system_category());
|
||||
}
|
||||
|
||||
inline asio::error_code make_error_code(netdb_errors e)
|
||||
{
|
||||
return asio::error_code(static_cast<int>(e), netdb_category);
|
||||
return asio::error_code(
|
||||
static_cast<int>(e), get_netdb_category());
|
||||
}
|
||||
|
||||
inline asio::error_code make_error_code(addrinfo_errors e)
|
||||
{
|
||||
return asio::error_code(static_cast<int>(e), addrinfo_category);
|
||||
return asio::error_code(
|
||||
static_cast<int>(e), get_addrinfo_category());
|
||||
}
|
||||
|
||||
inline asio::error_code make_error_code(misc_errors e)
|
||||
{
|
||||
return asio::error_code(static_cast<int>(e), misc_category);
|
||||
return asio::error_code(
|
||||
static_cast<int>(e), get_misc_category());
|
||||
}
|
||||
|
||||
inline asio::error_code make_error_code(ssl_errors e)
|
||||
{
|
||||
return asio::error_code(
|
||||
static_cast<int>(e), get_ssl_category());
|
||||
}
|
||||
|
||||
} // namespace error
|
||||
|
|
|
@ -41,10 +41,10 @@ namespace error
|
|||
system_category = ASIO_WIN_OR_POSIX(0, 0),
|
||||
|
||||
/// Error codes from NetDB functions.
|
||||
netdb_category = ASIO_WIN_OR_POSIX(system_category, 1),
|
||||
netdb_category = ASIO_WIN_OR_POSIX(_system_category, 1),
|
||||
|
||||
/// Error codes from getaddrinfo.
|
||||
addrinfo_category = ASIO_WIN_OR_POSIX(system_category, 2),
|
||||
addrinfo_category = ASIO_WIN_OR_POSIX(_system_category, 2),
|
||||
|
||||
/// Miscellaneous error codes.
|
||||
misc_category = ASIO_WIN_OR_POSIX(3, 3),
|
||||
|
@ -52,8 +52,19 @@ namespace error
|
|||
/// SSL error codes.
|
||||
ssl_category = ASIO_WIN_OR_POSIX(4, 4)
|
||||
};
|
||||
|
||||
// Category getters.
|
||||
inline error_category get_system_category() { return system_category; }
|
||||
inline error_category get_netdb_category() { return netdb_category; }
|
||||
inline error_category get_addrinfo_category() { return addrinfo_category; }
|
||||
inline error_category get_misc_category() { return misc_category; }
|
||||
inline error_category get_ssl_category() { return ssl_category; }
|
||||
|
||||
} // namespace error
|
||||
|
||||
/// Bring error category type into the asio namespace.
|
||||
typedef asio::error::error_category error_category;
|
||||
|
||||
/// Class to represent an error code value.
|
||||
class error_code
|
||||
{
|
||||
|
@ -69,7 +80,7 @@ public:
|
|||
}
|
||||
|
||||
/// Construct with specific error code and category.
|
||||
error_code(value_type v, error::error_category c)
|
||||
error_code(value_type v, error_category c)
|
||||
: value_(v),
|
||||
category_(c)
|
||||
{
|
||||
|
@ -89,7 +100,7 @@ public:
|
|||
}
|
||||
|
||||
/// Get the error category.
|
||||
error::error_category category() const
|
||||
error_category category() const
|
||||
{
|
||||
return category_;
|
||||
}
|
||||
|
@ -135,7 +146,7 @@ private:
|
|||
value_type value_;
|
||||
|
||||
// The category associated with the error code.
|
||||
error::error_category category_;
|
||||
error_category category_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
//
|
||||
// error_handler.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 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 ASIO_ERROR_HANDLER_HPP
|
||||
#define ASIO_ERROR_HANDLER_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class ignore_error_t
|
||||
{
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
template <typename Error>
|
||||
void operator()(const Error&) const
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class throw_error_t
|
||||
{
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
template <typename Error>
|
||||
void operator()(const Error& err) const
|
||||
{
|
||||
if (err)
|
||||
boost::throw_exception(err);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Target>
|
||||
class assign_error_t
|
||||
{
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
assign_error_t(Target& target)
|
||||
: target_(&target)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Error>
|
||||
void operator()(const Error& err) const
|
||||
{
|
||||
*target_ = err;
|
||||
}
|
||||
|
||||
private:
|
||||
Target* target_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @defgroup error_handler Error Handler Function Objects
|
||||
*
|
||||
* Function objects for custom error handling.
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/// Return a function object that always ignores the error.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
unspecified ignore_error();
|
||||
#else
|
||||
inline detail::ignore_error_t ignore_error()
|
||||
{
|
||||
return detail::ignore_error_t();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Return a function object that always throws the error.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
unspecified throw_error();
|
||||
#else
|
||||
inline detail::throw_error_t throw_error()
|
||||
{
|
||||
return detail::throw_error_t();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Return a function object that assigns the error to a variable.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
template <typename Target>
|
||||
unspecified assign_error(Target& target);
|
||||
#else
|
||||
template <typename Target>
|
||||
inline detail::assign_error_t<Target> assign_error(Target& target)
|
||||
{
|
||||
return detail::assign_error_t<Target>(target);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_ERROR_HANDLER_HPP
|
|
@ -35,11 +35,11 @@ inline std::string error_code::message() const
|
|||
return "Already open.";
|
||||
if (*this == error::not_found)
|
||||
return "Not found.";
|
||||
if (category_ == error::ssl_category)
|
||||
if (category_ == error::get_ssl_category())
|
||||
return "SSL error.";
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
value_type value = value_;
|
||||
if (category() != error::system_category && *this != error::eof)
|
||||
if (category() != error::get_system_category() && *this != error::eof)
|
||||
return "asio error";
|
||||
if (*this == error::eof)
|
||||
value = ERROR_HANDLE_EOF;
|
||||
|
@ -78,13 +78,13 @@ inline std::string error_code::message() const
|
|||
return "Service not found.";
|
||||
if (*this == error::socket_type_not_supported)
|
||||
return "Socket type not supported.";
|
||||
if (category() != error::system_category)
|
||||
if (category() != error::get_system_category())
|
||||
return "asio error";
|
||||
#if defined(__sun) || defined(__QNX__)
|
||||
return strerror(value_);
|
||||
#elif defined(__MACH__) && defined(__APPLE__) \
|
||||
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
|
||||
|| defined(_AIX)
|
||||
|| defined(_AIX) || defined(__hpux) || defined(__osf__)
|
||||
char buf[256] = "";
|
||||
strerror_r(value_, buf, sizeof(buf));
|
||||
return buf;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <limits>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/detail/dev_poll_reactor.hpp"
|
||||
#include "asio/detail/epoll_reactor.hpp"
|
||||
#include "asio/detail/kqueue_reactor.hpp"
|
||||
#include "asio/detail/select_reactor.hpp"
|
||||
|
@ -157,6 +158,11 @@ inline asio::io_service& io_service::work::io_service()
|
|||
return io_service_;
|
||||
}
|
||||
|
||||
inline asio::io_service& io_service::work::get_io_service()
|
||||
{
|
||||
return io_service_;
|
||||
}
|
||||
|
||||
inline io_service::service::service(asio::io_service& owner)
|
||||
: owner_(owner),
|
||||
type_info_(0),
|
||||
|
@ -173,6 +179,11 @@ inline asio::io_service& io_service::service::io_service()
|
|||
return owner_;
|
||||
}
|
||||
|
||||
inline asio::io_service& io_service::service::get_io_service()
|
||||
{
|
||||
return owner_;
|
||||
}
|
||||
|
||||
template <typename Service>
|
||||
inline Service& use_service(io_service& ios)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error_code.hpp"
|
||||
#include "asio/detail/dev_poll_reactor_fwd.hpp"
|
||||
#include "asio/detail/epoll_reactor_fwd.hpp"
|
||||
#include "asio/detail/kqueue_reactor_fwd.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
|
@ -39,6 +40,11 @@
|
|||
|
||||
namespace asio {
|
||||
|
||||
class io_service;
|
||||
template <typename Service> Service& use_service(io_service& ios);
|
||||
template <typename Service> void add_service(io_service& ios, Service* svc);
|
||||
template <typename Service> bool has_service(io_service& ios);
|
||||
|
||||
/// Provides core I/O functionality.
|
||||
/**
|
||||
* The io_service class provides the core I/O functionality for users of the
|
||||
|
@ -106,6 +112,8 @@ private:
|
|||
typedef detail::task_io_service<detail::epoll_reactor<false> > impl_type;
|
||||
#elif defined(ASIO_HAS_KQUEUE)
|
||||
typedef detail::task_io_service<detail::kqueue_reactor<false> > impl_type;
|
||||
#elif defined(ASIO_HAS_DEV_POLL)
|
||||
typedef detail::task_io_service<detail::dev_poll_reactor<false> > impl_type;
|
||||
#else
|
||||
typedef detail::task_io_service<detail::select_reactor<false> > impl_type;
|
||||
#endif
|
||||
|
@ -373,7 +381,8 @@ public:
|
|||
private:
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
detail::winsock_init<> init_;
|
||||
#elif defined(__sun) || defined(__QNX__)
|
||||
#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
|
||||
|| defined(__osf__)
|
||||
detail::signal_init<> init_;
|
||||
#endif
|
||||
|
||||
|
@ -421,9 +430,13 @@ public:
|
|||
*/
|
||||
~work();
|
||||
|
||||
/// Get the io_service associated with the work.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with the
|
||||
/// work.
|
||||
asio::io_service& io_service();
|
||||
|
||||
/// Get the io_service associated with the work.
|
||||
asio::io_service& get_io_service();
|
||||
|
||||
private:
|
||||
// Prevent assignment.
|
||||
void operator=(const work& other);
|
||||
|
@ -446,9 +459,13 @@ class io_service::service
|
|||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
/// Get the io_service object that owns the service.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service object that owns
|
||||
/// the service.
|
||||
asio::io_service& io_service();
|
||||
|
||||
/// Get the io_service object that owns the service.
|
||||
asio::io_service& get_io_service();
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
/**
|
||||
|
|
|
@ -268,7 +268,12 @@ std::basic_ostream<Elem, Traits>& operator<<(
|
|||
asio::error_code ec;
|
||||
std::string s = addr.to_string(ec);
|
||||
if (ec)
|
||||
os.setstate(std::ios_base::failbit);
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
for (std::string::iterator i = s.begin(); i != s.end(); ++i)
|
||||
os << os.widen(*i);
|
||||
|
|
|
@ -300,7 +300,7 @@ public:
|
|||
{
|
||||
using namespace std; // For memcmp.
|
||||
int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
|
||||
sizeof(asio::detail::in6_addr_type)) < 0;
|
||||
sizeof(asio::detail::in6_addr_type));
|
||||
if (memcmp_result < 0)
|
||||
return true;
|
||||
if (memcmp_result > 0)
|
||||
|
@ -386,7 +386,12 @@ std::basic_ostream<Elem, Traits>& operator<<(
|
|||
asio::error_code ec;
|
||||
std::string s = addr.to_string(ec);
|
||||
if (ec)
|
||||
os.setstate(std::ios_base::failbit);
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
for (std::string::iterator i = s.begin(); i != s.end(); ++i)
|
||||
os << os.widen(*i);
|
||||
|
|
|
@ -61,14 +61,6 @@ public:
|
|||
typedef asio::detail::socket_addr_type data_type;
|
||||
#endif
|
||||
|
||||
/// The type for the size of the endpoint structure. This type is dependent on
|
||||
/// the underlying implementation of the socket layer.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined size_type;
|
||||
#else
|
||||
typedef asio::detail::socket_addr_len_type size_type;
|
||||
#endif
|
||||
|
||||
/// Default constructor.
|
||||
basic_endpoint()
|
||||
: data_()
|
||||
|
@ -190,7 +182,7 @@ public:
|
|||
}
|
||||
|
||||
/// Get the underlying size of the endpoint in the native type.
|
||||
size_type size() const
|
||||
std::size_t size() const
|
||||
{
|
||||
if (is_v4(data_))
|
||||
return sizeof(asio::detail::sockaddr_in4_type);
|
||||
|
@ -199,9 +191,9 @@ public:
|
|||
}
|
||||
|
||||
/// Set the underlying size of the endpoint in the native type.
|
||||
void resize(size_type size)
|
||||
void resize(std::size_t size)
|
||||
{
|
||||
if (size > size_type(sizeof(data_)))
|
||||
if (size > sizeof(data_))
|
||||
{
|
||||
asio::system_error e(asio::error::invalid_argument);
|
||||
boost::throw_exception(e);
|
||||
|
@ -209,7 +201,7 @@ public:
|
|||
}
|
||||
|
||||
/// Get the capacity of the endpoint in the native type.
|
||||
size_type capacity() const
|
||||
std::size_t capacity() const
|
||||
{
|
||||
return sizeof(data_);
|
||||
}
|
||||
|
@ -349,11 +341,23 @@ std::ostream& operator<<(std::ostream& os,
|
|||
const basic_endpoint<InternetProtocol>& endpoint)
|
||||
{
|
||||
const address& addr = endpoint.address();
|
||||
if (addr.is_v4())
|
||||
os << addr.to_string();
|
||||
asio::error_code ec;
|
||||
std::string a = addr.to_string(ec);
|
||||
if (ec)
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
os << '[' << addr.to_string() << ']';
|
||||
os << ':' << endpoint.port();
|
||||
{
|
||||
if (addr.is_v4())
|
||||
os << a;
|
||||
else
|
||||
os << '[' << a << ']';
|
||||
os << ':' << endpoint.port();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
|
@ -363,11 +367,23 @@ std::basic_ostream<Elem, Traits>& operator<<(
|
|||
const basic_endpoint<InternetProtocol>& endpoint)
|
||||
{
|
||||
const address& addr = endpoint.address();
|
||||
if (addr.is_v4())
|
||||
os << addr.to_string();
|
||||
asio::error_code ec;
|
||||
std::string a = addr.to_string(ec);
|
||||
if (ec)
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
os << '[' << addr.to_string() << ']';
|
||||
os << ':' << endpoint.port();
|
||||
{
|
||||
if (addr.is_v4())
|
||||
os << a;
|
||||
else
|
||||
os << '[' << a << ']';
|
||||
os << ':' << endpoint.port();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
|
|
|
@ -80,9 +80,7 @@ public:
|
|||
{
|
||||
using namespace std; // For memcpy.
|
||||
typename InternetProtocol::endpoint endpoint;
|
||||
endpoint.resize(
|
||||
static_cast<asio::detail::socket_addr_len_type>(
|
||||
address_info->ai_addrlen));
|
||||
endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));
|
||||
memcpy(endpoint.data(), address_info->ai_addr,
|
||||
address_info->ai_addrlen);
|
||||
iter.values_->push_back(
|
||||
|
|
|
@ -32,52 +32,60 @@ namespace ip {
|
|||
namespace detail {
|
||||
namespace socket_option {
|
||||
|
||||
// Helper template for implementing boolean-based options.
|
||||
// Helper template for implementing multicast enable loopback options.
|
||||
template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
||||
class boolean
|
||||
class multicast_enable_loopback
|
||||
{
|
||||
public:
|
||||
#if defined(__sun)
|
||||
typedef unsigned char value_type;
|
||||
#if defined(__sun) || defined(__osf__)
|
||||
typedef unsigned char ipv4_value_type;
|
||||
typedef unsigned char ipv6_value_type;
|
||||
#elif defined(_AIX) || defined(__hpux)
|
||||
typedef unsigned char ipv4_value_type;
|
||||
typedef unsigned int ipv6_value_type;
|
||||
#else
|
||||
typedef int value_type;
|
||||
typedef int ipv4_value_type;
|
||||
typedef int ipv6_value_type;
|
||||
#endif
|
||||
|
||||
// Default constructor.
|
||||
boolean()
|
||||
: value_(0)
|
||||
multicast_enable_loopback()
|
||||
: ipv4_value_(0),
|
||||
ipv6_value_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Construct with a specific option value.
|
||||
explicit boolean(bool v)
|
||||
: value_(v ? 1 : 0)
|
||||
explicit multicast_enable_loopback(bool v)
|
||||
: ipv4_value_(v ? 1 : 0),
|
||||
ipv6_value_(v ? 1 : 0)
|
||||
{
|
||||
}
|
||||
|
||||
// Set the value of the boolean.
|
||||
boolean& operator=(bool v)
|
||||
multicast_enable_loopback& operator=(bool v)
|
||||
{
|
||||
value_ = v ? 1 : 0;
|
||||
ipv4_value_ = v ? 1 : 0;
|
||||
ipv6_value_ = v ? 1 : 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Get the current value of the boolean.
|
||||
bool value() const
|
||||
{
|
||||
return !!value_;
|
||||
return !!ipv4_value_;
|
||||
}
|
||||
|
||||
// Convert to bool.
|
||||
operator bool() const
|
||||
{
|
||||
return !!value_;
|
||||
return !!ipv4_value_;
|
||||
}
|
||||
|
||||
// Test for false.
|
||||
bool operator!() const
|
||||
{
|
||||
return !value_;
|
||||
return !ipv4_value_;
|
||||
}
|
||||
|
||||
// Get the level of the socket option.
|
||||
|
@ -100,35 +108,58 @@ public:
|
|||
|
||||
// Get the address of the boolean data.
|
||||
template <typename Protocol>
|
||||
value_type* data(const Protocol&)
|
||||
void* data(const Protocol& protocol)
|
||||
{
|
||||
return &value_;
|
||||
if (protocol.family() == PF_INET6)
|
||||
return &ipv6_value_;
|
||||
return &ipv4_value_;
|
||||
}
|
||||
|
||||
// Get the address of the boolean data.
|
||||
template <typename Protocol>
|
||||
const value_type* data(const Protocol&) const
|
||||
const void* data(const Protocol& protocol) const
|
||||
{
|
||||
return &value_;
|
||||
if (protocol.family() == PF_INET6)
|
||||
return &ipv6_value_;
|
||||
return &ipv4_value_;
|
||||
}
|
||||
|
||||
// Get the size of the boolean data.
|
||||
template <typename Protocol>
|
||||
std::size_t size(const Protocol&) const
|
||||
std::size_t size(const Protocol& protocol) const
|
||||
{
|
||||
return sizeof(value_);
|
||||
if (protocol.family() == PF_INET6)
|
||||
return sizeof(ipv6_value_);
|
||||
return sizeof(ipv4_value_);
|
||||
}
|
||||
|
||||
// Set the size of the boolean data.
|
||||
template <typename Protocol>
|
||||
void resize(const Protocol&, std::size_t s)
|
||||
void resize(const Protocol& protocol, std::size_t s)
|
||||
{
|
||||
if (s != sizeof(value_))
|
||||
throw std::length_error("boolean socket option resize");
|
||||
if (protocol.family() == PF_INET6)
|
||||
{
|
||||
if (s != sizeof(ipv6_value_))
|
||||
{
|
||||
throw std::length_error(
|
||||
"multicast_enable_loopback socket option resize");
|
||||
}
|
||||
ipv4_value_ = ipv6_value_ ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s != sizeof(ipv4_value_))
|
||||
{
|
||||
throw std::length_error(
|
||||
"multicast_enable_loopback socket option resize");
|
||||
}
|
||||
ipv6_value_ = ipv4_value_ ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
value_type value_;
|
||||
ipv4_value_type ipv4_value_;
|
||||
ipv6_value_type ipv6_value_;
|
||||
};
|
||||
|
||||
// Helper template for implementing unicast hops options.
|
||||
|
@ -206,6 +237,10 @@ public:
|
|||
{
|
||||
if (s != sizeof(value_))
|
||||
throw std::length_error("unicast hops socket option resize");
|
||||
#if defined(__hpux)
|
||||
if (value_ < 0)
|
||||
value_ = value_ & 0xFF;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -217,6 +252,13 @@ template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
|||
class multicast_hops
|
||||
{
|
||||
public:
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
typedef int ipv4_value_type;
|
||||
#else
|
||||
typedef unsigned char ipv4_value_type;
|
||||
#endif
|
||||
typedef int ipv6_value_type;
|
||||
|
||||
// Default constructor.
|
||||
multicast_hops()
|
||||
: ipv4_value_(0),
|
||||
|
@ -229,7 +271,7 @@ public:
|
|||
{
|
||||
if (v < 0 || v > 255)
|
||||
throw std::out_of_range("multicast hops value out of range");
|
||||
ipv4_value_ = static_cast<unsigned char>(v);
|
||||
ipv4_value_ = (ipv4_value_type)v;
|
||||
ipv6_value_ = v;
|
||||
}
|
||||
|
||||
|
@ -238,7 +280,7 @@ public:
|
|||
{
|
||||
if (v < 0 || v > 255)
|
||||
throw std::out_of_range("multicast hops value out of range");
|
||||
ipv4_value_ = static_cast<unsigned char>(v);
|
||||
ipv4_value_ = (ipv4_value_type)v;
|
||||
ipv6_value_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
@ -307,7 +349,7 @@ public:
|
|||
else if (ipv6_value_ > 255)
|
||||
ipv4_value_ = 255;
|
||||
else
|
||||
ipv4_value_ = static_cast<unsigned char>(ipv6_value_);
|
||||
ipv4_value_ = (ipv4_value_type)ipv6_value_;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -318,8 +360,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
unsigned char ipv4_value_;
|
||||
int ipv6_value_;
|
||||
ipv4_value_type ipv4_value_;
|
||||
ipv6_value_type ipv6_value_;
|
||||
};
|
||||
|
||||
// Helper template for implementing ip_mreq-based options.
|
||||
|
@ -477,7 +519,7 @@ public:
|
|||
}
|
||||
|
||||
// Construct with IPv6 interface.
|
||||
explicit network_interface(unsigned long ipv6_interface)
|
||||
explicit network_interface(unsigned int ipv6_interface)
|
||||
{
|
||||
ipv4_value_.s_addr =
|
||||
asio::detail::socket_ops::host_to_network_long(
|
||||
|
@ -523,7 +565,7 @@ public:
|
|||
|
||||
private:
|
||||
asio::detail::in4_addr_type ipv4_value_;
|
||||
unsigned long ipv6_value_;
|
||||
unsigned int ipv6_value_;
|
||||
};
|
||||
|
||||
} // namespace socket_option
|
||||
|
|
|
@ -167,7 +167,7 @@ typedef asio::ip::detail::socket_option::multicast_hops<
|
|||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined enable_loopback;
|
||||
#else
|
||||
typedef asio::ip::detail::socket_option::boolean<
|
||||
typedef asio::ip::detail::socket_option::multicast_enable_loopback<
|
||||
IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP>
|
||||
enable_loopback;
|
||||
#endif
|
||||
|
|
|
@ -27,17 +27,17 @@ namespace placeholders {
|
|||
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// An argument placeholder, for use with @ref boost_bind, that corresponds to
|
||||
/// An argument placeholder, for use with boost::bind(), that corresponds to
|
||||
/// the error argument of a handler for any of the asynchronous functions.
|
||||
unspecified error;
|
||||
|
||||
/// An argument placeholder, for use with @ref boost_bind, that corresponds to
|
||||
/// An argument placeholder, for use with boost::bind(), that corresponds to
|
||||
/// the bytes_transferred argument of a handler for asynchronous functions such
|
||||
/// as asio::basic_stream_socket::async_write_some or
|
||||
/// asio::async_write.
|
||||
unspecified bytes_transferred;
|
||||
|
||||
/// An argument placeholder, for use with @ref boost_bind, that corresponds to
|
||||
/// An argument placeholder, for use with boost::bind(), that corresponds to
|
||||
/// the iterator argument of a handler for asynchronous functions such as
|
||||
/// asio::basic_resolver::resolve.
|
||||
unspecified iterator;
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
//
|
||||
// resolver_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 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 ASIO_RESOLVER_SERVICE_HPP
|
||||
#define ASIO_RESOLVER_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/io_service.hpp"
|
||||
#include "asio/detail/resolver_service.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Default service implementation for a resolver.
|
||||
template <typename Protocol>
|
||||
class resolver_service
|
||||
: public asio::io_service::service
|
||||
{
|
||||
public:
|
||||
/// The protocol type.
|
||||
typedef Protocol protocol_type;
|
||||
|
||||
/// The endpoint type.
|
||||
typedef typename Protocol::endpoint endpoint_type;
|
||||
|
||||
/// The query type.
|
||||
typedef typename Protocol::resolver_query query_type;
|
||||
|
||||
/// The iterator type.
|
||||
typedef typename Protocol::resolver_iterator iterator_type;
|
||||
|
||||
private:
|
||||
// The type of the platform-specific implementation.
|
||||
typedef detail::resolver_service<Protocol> service_impl_type;
|
||||
|
||||
public:
|
||||
/// The type of a resolver implementation.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined implementation_type;
|
||||
#else
|
||||
typedef typename service_impl_type::implementation_type implementation_type;
|
||||
#endif
|
||||
|
||||
/// Construct a new resolver service for the specified io_service.
|
||||
explicit resolver_service(asio::io_service& io_service)
|
||||
: asio::io_service::service(io_service),
|
||||
service_impl_(asio::use_service<service_impl_type>(io_service))
|
||||
{
|
||||
}
|
||||
|
||||
/// Destroy all user-defined handler objects owned by the service.
|
||||
void shutdown_service()
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a new resolver implementation.
|
||||
void construct(implementation_type& impl)
|
||||
{
|
||||
service_impl_.construct(impl);
|
||||
}
|
||||
|
||||
/// Destroy a resolver implementation.
|
||||
void destroy(implementation_type& impl)
|
||||
{
|
||||
service_impl_.destroy(impl);
|
||||
}
|
||||
|
||||
/// Cancel pending asynchronous operations.
|
||||
void cancel(implementation_type& impl)
|
||||
{
|
||||
service_impl_.cancel(impl);
|
||||
}
|
||||
|
||||
/// Resolve a query to a list of entries.
|
||||
template <typename Error_Handler>
|
||||
iterator_type resolve(implementation_type& impl, const query_type& query,
|
||||
Error_Handler error_handler)
|
||||
{
|
||||
return service_impl_.resolve(impl, query, error_handler);
|
||||
}
|
||||
|
||||
/// Asynchronously resolve a query to a list of entries.
|
||||
template <typename Handler>
|
||||
void async_resolve(implementation_type& impl, const query_type& query,
|
||||
Handler handler)
|
||||
{
|
||||
service_impl_.async_resolve(impl, query, handler);
|
||||
}
|
||||
|
||||
/// Resolve an endpoint to a list of entries.
|
||||
template <typename Error_Handler>
|
||||
iterator_type resolve(implementation_type& impl,
|
||||
const endpoint_type& endpoint, Error_Handler error_handler)
|
||||
{
|
||||
return service_impl_.resolve(impl, endpoint, error_handler);
|
||||
}
|
||||
|
||||
/// Asynchronously resolve an endpoint to a list of entries.
|
||||
template <typename Handler>
|
||||
void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
|
||||
Handler handler)
|
||||
{
|
||||
return service_impl_.async_resolve(impl, endpoint, handler);
|
||||
}
|
||||
|
||||
private:
|
||||
// The service that provides the platform-specific implementation.
|
||||
service_impl_type& service_impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_RESOLVER_SERVICE_HPP
|
|
@ -60,6 +60,9 @@ private:
|
|||
#elif defined(ASIO_HAS_KQUEUE)
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::kqueue_reactor<false> > service_impl_type;
|
||||
#elif defined(ASIO_HAS_DEV_POLL)
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::dev_poll_reactor<false> > service_impl_type;
|
||||
#else
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::select_reactor<false> > service_impl_type;
|
||||
|
|
|
@ -179,7 +179,7 @@ public:
|
|||
else
|
||||
{
|
||||
return handler_(asio::error_code(
|
||||
error_code, asio::error::ssl_category), rc);
|
||||
error_code, asio::error::get_ssl_category()), rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ public:
|
|||
typedef handshake_handler<Stream, Handler> connect_handler;
|
||||
|
||||
connect_handler* local_handler =
|
||||
new connect_handler(handler, io_service());
|
||||
new connect_handler(handler, get_io_service());
|
||||
|
||||
openssl_operation<Stream>* op = new openssl_operation<Stream>
|
||||
(
|
||||
|
@ -259,7 +259,7 @@ public:
|
|||
);
|
||||
local_handler->set_operation(op);
|
||||
|
||||
io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
}
|
||||
|
||||
// Shut down SSL on the stream.
|
||||
|
@ -294,7 +294,7 @@ public:
|
|||
typedef shutdown_handler<Stream, Handler> disconnect_handler;
|
||||
|
||||
disconnect_handler* local_handler =
|
||||
new disconnect_handler(handler, io_service());
|
||||
new disconnect_handler(handler, get_io_service());
|
||||
|
||||
openssl_operation<Stream>* op = new openssl_operation<Stream>
|
||||
(
|
||||
|
@ -313,7 +313,7 @@ public:
|
|||
);
|
||||
local_handler->set_operation(op);
|
||||
|
||||
io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
}
|
||||
|
||||
// Write some data to the stream.
|
||||
|
@ -354,7 +354,7 @@ public:
|
|||
{
|
||||
typedef io_handler<Stream, Handler> send_handler;
|
||||
|
||||
send_handler* local_handler = new send_handler(handler, io_service());
|
||||
send_handler* local_handler = new send_handler(handler, get_io_service());
|
||||
|
||||
boost::function<int (SSL*)> send_func =
|
||||
boost::bind(&::SSL_write, boost::arg<1>(),
|
||||
|
@ -378,7 +378,7 @@ public:
|
|||
);
|
||||
local_handler->set_operation(op);
|
||||
|
||||
io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
}
|
||||
|
||||
// Read some data from the stream.
|
||||
|
@ -419,7 +419,7 @@ public:
|
|||
{
|
||||
typedef io_handler<Stream, Handler> recv_handler;
|
||||
|
||||
recv_handler* local_handler = new recv_handler(handler, io_service());
|
||||
recv_handler* local_handler = new recv_handler(handler, get_io_service());
|
||||
|
||||
boost::function<int (SSL*)> recv_func =
|
||||
boost::bind(&::SSL_read, boost::arg<1>(),
|
||||
|
@ -443,7 +443,7 @@ public:
|
|||
);
|
||||
local_handler->set_operation(op);
|
||||
|
||||
io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
|
||||
}
|
||||
|
||||
// Peek at the incoming data on the stream.
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
template <typename Arg, typename Context_Service>
|
||||
explicit stream(Arg& arg, basic_context<Context_Service>& context)
|
||||
: next_layer_(arg),
|
||||
service_(asio::use_service<Service>(next_layer_.io_service())),
|
||||
service_(asio::use_service<Service>(next_layer_.get_io_service())),
|
||||
impl_(service_.null())
|
||||
{
|
||||
service_.create(impl_, next_layer_, context);
|
||||
|
@ -97,7 +97,8 @@ public:
|
|||
service_.destroy(impl_, next_layer_);
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
/**
|
||||
* This function may be used to obtain the io_service object that the stream
|
||||
* uses to dispatch handlers for asynchronous operations.
|
||||
|
@ -107,7 +108,20 @@ public:
|
|||
*/
|
||||
asio::io_service& io_service()
|
||||
{
|
||||
return next_layer_.io_service();
|
||||
return next_layer_.get_io_service();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the object.
|
||||
/**
|
||||
* This function may be used to obtain the io_service object that the stream
|
||||
* uses to dispatch handlers for asynchronous operations.
|
||||
*
|
||||
* @return A reference to the io_service object that stream will use to
|
||||
* dispatch handlers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return next_layer_.get_io_service();
|
||||
}
|
||||
|
||||
/// Get a reference to the next layer.
|
||||
|
|
|
@ -65,7 +65,8 @@ public:
|
|||
service_.destroy(impl_);
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the strand.
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the strand.
|
||||
/**
|
||||
* This function may be used to obtain the io_service object that the strand
|
||||
* uses to dispatch handlers for asynchronous operations.
|
||||
|
@ -75,7 +76,20 @@ public:
|
|||
*/
|
||||
asio::io_service& io_service()
|
||||
{
|
||||
return service_.io_service();
|
||||
return service_.get_io_service();
|
||||
}
|
||||
|
||||
/// Get the io_service associated with the strand.
|
||||
/**
|
||||
* This function may be used to obtain the io_service object that the strand
|
||||
* uses to dispatch handlers for asynchronous operations.
|
||||
*
|
||||
* @return A reference to the io_service object that the strand will use to
|
||||
* dispatch handlers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return service_.get_io_service();
|
||||
}
|
||||
|
||||
/// Request the strand to invoke the given handler.
|
||||
|
|
|
@ -64,6 +64,9 @@ private:
|
|||
#elif defined(ASIO_HAS_KQUEUE)
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::kqueue_reactor<false> > service_impl_type;
|
||||
#elif defined(ASIO_HAS_DEV_POLL)
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::dev_poll_reactor<false> > service_impl_type;
|
||||
#else
|
||||
typedef detail::reactive_socket_service<
|
||||
Protocol, detail::select_reactor<false> > service_impl_type;
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
//
|
||||
// error.hpp
|
||||
// ~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2006 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 ASIO_SYSTEM_EXCEPTION_HPP
|
||||
#define ASIO_SYSTEM_EXCEPTION_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
# include <iostream>
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/detail/win_local_free_on_block_exit.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// The system_exception class is used to represent system conditions that
|
||||
/// prevent the library from operating correctly.
|
||||
class system_exception
|
||||
: public std::exception
|
||||
{
|
||||
public:
|
||||
/// Construct with a specific context and error code.
|
||||
system_exception(const std::string& context, int code)
|
||||
: context_(context),
|
||||
code_(code)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
system_exception(const system_exception& e)
|
||||
: std::exception(e),
|
||||
context_(e.context_),
|
||||
code_(e.code_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~system_exception() throw ()
|
||||
{
|
||||
}
|
||||
|
||||
/// Assignment operator.
|
||||
system_exception& operator=(const system_exception& e)
|
||||
{
|
||||
context_ = e.context_;
|
||||
code_ = e.code_;
|
||||
what_.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a string representation of the exception.
|
||||
virtual const char* what() const throw ()
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
try
|
||||
{
|
||||
if (!what_)
|
||||
{
|
||||
char* msg = 0;
|
||||
DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
| FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS, 0, code_,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0);
|
||||
detail::win_local_free_on_block_exit local_free_obj(msg);
|
||||
if (length && msg[length - 1] == '\n')
|
||||
msg[--length] = '\0';
|
||||
if (length && msg[length - 1] == '\r')
|
||||
msg[--length] = '\0';
|
||||
if (length)
|
||||
{
|
||||
std::string tmp(context_);
|
||||
tmp += ": ";
|
||||
tmp += msg;
|
||||
what_.reset(new std::string(tmp));
|
||||
}
|
||||
else
|
||||
{
|
||||
return "asio system_exception";
|
||||
}
|
||||
}
|
||||
return what_->c_str();
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
return "asio system_exception";
|
||||
}
|
||||
#elif defined(__sun) || defined(__QNX__)
|
||||
return strerror(code_);
|
||||
#elif defined(__MACH__) && defined(__APPLE__) \
|
||||
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
try
|
||||
{
|
||||
char buf[256] = "";
|
||||
strerror_r(code_, buf, sizeof(buf));
|
||||
std::string tmp(context_);
|
||||
tmp += ": ";
|
||||
tmp += buf;
|
||||
what_.reset(new std::string(tmp));
|
||||
return what_->c_str();
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
return "asio system_exception";
|
||||
}
|
||||
#else
|
||||
try
|
||||
{
|
||||
char buf[256] = "";
|
||||
std::string tmp(context_);
|
||||
tmp += ": ";
|
||||
tmp += strerror_r(code_, buf, sizeof(buf));
|
||||
what_.reset(new std::string(tmp));
|
||||
return what_->c_str();
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
return "asio system_exception";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Get the implementation-defined context associated with the exception.
|
||||
const std::string& context() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
|
||||
/// Get the implementation-defined code associated with the exception.
|
||||
int code() const
|
||||
{
|
||||
return code_;
|
||||
}
|
||||
|
||||
private:
|
||||
// The context associated with the error.
|
||||
std::string context_;
|
||||
|
||||
// The code associated with the error.
|
||||
int code_;
|
||||
|
||||
// The string representation of the error.
|
||||
mutable boost::scoped_ptr<std::string> what_;
|
||||
};
|
||||
|
||||
/// Output the string associated with a system exception.
|
||||
/**
|
||||
* Used to output a human-readable string that is associated with a system
|
||||
* exception.
|
||||
*
|
||||
* @param os The output stream to which the string will be written.
|
||||
*
|
||||
* @param e The exception to be written.
|
||||
*
|
||||
* @return The output stream.
|
||||
*
|
||||
* @relates asio::system_exception
|
||||
*/
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
std::ostream& operator<<(std::ostream& os, const system_exception& e)
|
||||
{
|
||||
os << e.what();
|
||||
return os;
|
||||
}
|
||||
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
template <typename Ostream>
|
||||
Ostream& operator<<(Ostream& os, const system_exception& e)
|
||||
{
|
||||
os << e.what();
|
||||
return os;
|
||||
}
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_SYSTEM_EXCEPTION_HPP
|
Loading…
Reference in New Issue