diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-05-06 17:44:27 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-05-06 17:44:27 (GMT) |
commit | d76ada0ab59634e3333f9eb5a92d0e850f60d7bf (patch) | |
tree | 5eaae441173fad2ec19ba67d6589f28ecd740991 /3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp | |
parent | 6f49e5abee37d37b351d68c01374232eccdac458 (diff) | |
download | swift-contrib-d76ada0ab59634e3333f9eb5a92d0e850f60d7bf.zip swift-contrib-d76ada0ab59634e3333f9eb5a92d0e850f60d7bf.tar.bz2 |
Updated Boost to 1.43.0.
Diffstat (limited to '3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp | 247 |
1 files changed, 166 insertions, 81 deletions
diff --git a/3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp b/3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp index 3270cd6..f9b7a98 100644 --- a/3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp @@ -26,9 +26,13 @@ #include <boost/asio/error.hpp> #include <boost/asio/io_service.hpp> +#include <boost/asio/ip/basic_resolver_iterator.hpp> +#include <boost/asio/ip/basic_resolver_query.hpp> #include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/fenced_block.hpp> #include <boost/asio/detail/mutex.hpp> #include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/operation.hpp> #include <boost/asio/detail/service_base.hpp> #include <boost/asio/detail/socket_ops.hpp> #include <boost/asio/detail/socket_types.hpp> @@ -79,17 +83,20 @@ public: typedef typename Protocol::endpoint endpoint_type; // The query type. - typedef typename Protocol::resolver_query query_type; + typedef boost::asio::ip::basic_resolver_query<Protocol> query_type; // The iterator type. - typedef typename Protocol::resolver_iterator iterator_type; + typedef boost::asio::ip::basic_resolver_iterator<Protocol> iterator_type; // Constructor. resolver_service(boost::asio::io_service& io_service) : boost::asio::detail::service_base< resolver_service<Protocol> >(io_service), mutex_(), + io_service_impl_(boost::asio::use_service<io_service_impl>(io_service)), work_io_service_(new boost::asio::io_service), + work_io_service_impl_(boost::asio::use_service< + io_service_impl>(*work_io_service_)), work_(new boost::asio::io_service::work(*work_io_service_)), work_thread_(0) { @@ -143,7 +150,7 @@ public: std::string service_name = query.service_name(); boost::asio::detail::addrinfo_type hints = query.hints(); - socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, + socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0, service_name.c_str(), &hints, &address_info, ec); auto_addrinfo auto_address_info(address_info); @@ -154,54 +161,84 @@ public: } template <typename Handler> - class resolve_query_handler + class resolve_op + : public operation { public: - resolve_query_handler(implementation_type impl, const query_type& query, - boost::asio::io_service& io_service, Handler handler) - : impl_(impl), + resolve_op(implementation_type impl, const query_type& query, + io_service_impl& io_service_impl, Handler handler) + : operation(&resolve_op::do_complete), + impl_(impl), query_(query), - io_service_(io_service), - work_(io_service), + io_service_impl_(io_service_impl), handler_(handler) { } - void operator()() + static void do_complete(io_service_impl* owner, operation* base, + boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) { - // Check if the operation has been cancelled. - if (impl_.expired()) + // Take ownership of the operation object. + resolve_op* o(static_cast<resolve_op*>(base)); + typedef handler_alloc_traits<Handler, resolve_op> alloc_traits; + handler_ptr<alloc_traits> ptr(o->handler_, o); + + if (owner) { - iterator_type iterator; - io_service_.post(boost::asio::detail::bind_handler(handler_, - boost::asio::error::operation_aborted, iterator)); - return; + if (owner != &o->io_service_impl_) + { + // The operation is being run on the worker io_service. Time to + // perform the resolver operation. + + if (o->impl_.expired()) + { + // THe operation has been cancelled. + o->ec_ = boost::asio::error::operation_aborted; + } + else + { + // Perform the blocking host resolution operation. + boost::asio::detail::addrinfo_type* address_info = 0; + std::string host_name = o->query_.host_name(); + std::string service_name = o->query_.service_name(); + boost::asio::detail::addrinfo_type hints = o->query_.hints(); + socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0, + service_name.c_str(), &hints, &address_info, o->ec_); + auto_addrinfo auto_address_info(address_info); + o->iter_ = iterator_type::create( + address_info, host_name, service_name); + } + + o->io_service_impl_.post_deferred_completion(o); + ptr.release(); + } + else + { + // The operation has been returned to the main io_serice. The + // completion handler is ready to be delivered. + + // Make a copy of the handler so that the memory can be deallocated + // before the upcall is made. Even if we're not about to make an + // upcall, a sub-object of the handler may be the true owner of the + // memory associated with the handler. Consequently, a local copy of + // the handler is required to ensure that any owning sub-object + // remains valid until after we have deallocated the memory here. + detail::binder2<Handler, boost::system::error_code, iterator_type> + handler(o->handler_, o->ec_, o->iter_); + ptr.reset(); + boost::asio::detail::fenced_block b; + boost_asio_handler_invoke_helpers::invoke(handler, handler); + } } - - // Perform the blocking host resolution operation. - boost::asio::detail::addrinfo_type* address_info = 0; - std::string host_name = query_.host_name(); - std::string service_name = query_.service_name(); - boost::asio::detail::addrinfo_type hints = query_.hints(); - boost::system::error_code ec; - socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, - service_name.c_str(), &hints, &address_info, ec); - auto_addrinfo auto_address_info(address_info); - - // Invoke the handler and pass the result. - iterator_type iterator; - if (!ec) - iterator = iterator_type::create(address_info, host_name, service_name); - io_service_.post(boost::asio::detail::bind_handler( - handler_, ec, iterator)); } private: boost::weak_ptr<void> impl_; query_type query_; - boost::asio::io_service& io_service_; - boost::asio::io_service::work work_; + io_service_impl& io_service_impl_; Handler handler_; + boost::system::error_code ec_; + iterator_type iter_; }; // Asynchronously resolve a query to a list of entries. @@ -209,12 +246,19 @@ public: void async_resolve(implementation_type& impl, const query_type& query, Handler handler) { + // Allocate and construct an operation to wrap the handler. + typedef resolve_op<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, + impl, query, io_service_impl_, handler); + if (work_io_service_) { start_work_thread(); - work_io_service_->post( - resolve_query_handler<Handler>( - impl, query, this->get_io_service(), handler)); + io_service_impl_.work_started(); + work_io_service_impl_.post_immediate_completion(ptr.get()); + ptr.release(); } } @@ -243,61 +287,89 @@ public: } template <typename Handler> - class resolve_endpoint_handler + class resolve_endpoint_op + : public operation { public: - resolve_endpoint_handler(implementation_type impl, - const endpoint_type& endpoint, boost::asio::io_service& io_service, - Handler handler) - : impl_(impl), - endpoint_(endpoint), - io_service_(io_service), - work_(io_service), + resolve_endpoint_op(implementation_type impl, const endpoint_type& ep, + io_service_impl& io_service_impl, Handler handler) + : operation(&resolve_endpoint_op::do_complete), + impl_(impl), + ep_(ep), + io_service_impl_(io_service_impl), handler_(handler) { } - void operator()() + static void do_complete(io_service_impl* owner, operation* base, + boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) { - // Check if the operation has been cancelled. - if (impl_.expired()) - { - iterator_type iterator; - io_service_.post(boost::asio::detail::bind_handler(handler_, - boost::asio::error::operation_aborted, iterator)); - return; - } - + // Take ownership of the operation object. + resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base)); + typedef handler_alloc_traits<Handler, resolve_endpoint_op> alloc_traits; + handler_ptr<alloc_traits> ptr(o->handler_, o); - // First try resolving with the service name. If that fails try resolving - // but allow the service to be returned as a number. - char host_name[NI_MAXHOST]; - char service_name[NI_MAXSERV]; - int flags = endpoint_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; - boost::system::error_code ec; - socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - if (ec) + if (owner) { - flags |= NI_NUMERICSERV; - socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); + if (owner != &o->io_service_impl_) + { + // The operation is being run on the worker io_service. Time to + // perform the resolver operation. + + if (o->impl_.expired()) + { + // THe operation has been cancelled. + o->ec_ = boost::asio::error::operation_aborted; + } + else + { + // Perform the blocking endoint resolution operation. + char host_name[NI_MAXHOST]; + char service_name[NI_MAXSERV]; + int flags = o->ep_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; + socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(), + host_name, NI_MAXHOST, service_name, + NI_MAXSERV, flags, o->ec_); + if (o->ec_) + { + flags |= NI_NUMERICSERV; + socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(), + host_name, NI_MAXHOST, service_name, + NI_MAXSERV, flags, o->ec_); + } + o->iter_ = iterator_type::create(o->ep_, host_name, service_name); + } + + o->io_service_impl_.post_deferred_completion(o); + ptr.release(); + } + else + { + // The operation has been returned to the main io_serice. The + // completion handler is ready to be delivered. + + // Make a copy of the handler so that the memory can be deallocated + // before the upcall is made. Even if we're not about to make an + // upcall, a sub-object of the handler may be the true owner of the + // memory associated with the handler. Consequently, a local copy of + // the handler is required to ensure that any owning sub-object + // remains valid until after we have deallocated the memory here. + detail::binder2<Handler, boost::system::error_code, iterator_type> + handler(o->handler_, o->ec_, o->iter_); + ptr.reset(); + boost::asio::detail::fenced_block b; + boost_asio_handler_invoke_helpers::invoke(handler, handler); + } } - - // Invoke the handler and pass the result. - iterator_type iterator; - if (!ec) - iterator = iterator_type::create(endpoint_, host_name, service_name); - io_service_.post(boost::asio::detail::bind_handler( - handler_, ec, iterator)); } private: boost::weak_ptr<void> impl_; - endpoint_type endpoint_; - boost::asio::io_service& io_service_; - boost::asio::io_service::work work_; + endpoint_type ep_; + io_service_impl& io_service_impl_; Handler handler_; + boost::system::error_code ec_; + iterator_type iter_; }; // Asynchronously resolve an endpoint to a list of entries. @@ -305,12 +377,19 @@ public: void async_resolve(implementation_type& impl, const endpoint_type& endpoint, Handler handler) { + // Allocate and construct an operation to wrap the handler. + typedef resolve_endpoint_op<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, + impl, endpoint, io_service_impl_, handler); + if (work_io_service_) { start_work_thread(); - work_io_service_->post( - resolve_endpoint_handler<Handler>( - impl, endpoint, this->get_io_service(), handler)); + io_service_impl_.work_started(); + work_io_service_impl_.post_immediate_completion(ptr.get()); + ptr.release(); } } @@ -340,9 +419,15 @@ private: // Mutex to protect access to internal data. boost::asio::detail::mutex mutex_; + // The io_service implementation used to post completions. + io_service_impl& io_service_impl_; + // Private io_service used for performing asynchronous host resolution. boost::scoped_ptr<boost::asio::io_service> work_io_service_; + // The work io_service implementation used to post completions. + io_service_impl& work_io_service_impl_; + // Work for the private io_service to perform. boost::scoped_ptr<boost::asio::io_service::work> work_; |