diff options
174 files changed, 8671 insertions, 9160 deletions
diff --git a/3rdParty/Boost/src/boost/array.hpp b/3rdParty/Boost/src/boost/array.hpp index d58b93a..6496469 100644 --- a/3rdParty/Boost/src/boost/array.hpp +++ b/3rdParty/Boost/src/boost/array.hpp @@ -13,6 +13,10 @@   * accompanying file LICENSE_1_0.txt or copy at   * http://www.boost.org/LICENSE_1_0.txt)   * + * 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group. + *		See <http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776> or Trac issue #3168 + *		Eventually, we should remove "assign" which is now a synonym for "fill" (Marshall Clow) + * 10 Mar 2010 - added workaround for SUNCC and !STLPort [trac #3893] (Marshall Clow)   * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis)   * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.   * 05 Aug 2001 - minor update (Nico Josuttis) @@ -29,6 +33,8 @@  #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)    # pragma warning(push)    # pragma warning(disable:4996) // 'std::equal': Function call with parameters that may be unsafe +# pragma warning(disable:4510) // boost::array<T,N>' : default constructor could not be generated  +# pragma warning(disable:4610) // warning C4610: class 'boost::array<T,N>' can never be instantiated - user defined constructor required   #endif  #include <cstddef> @@ -78,6 +84,11 @@ namespace boost {                                        reference, iterator, reference> > reverse_iterator;          typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,                                        const_reference, iterator, reference> > const_reverse_iterator; +#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)  +        typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,  +              value_type, reference, iterator, difference_type> reverse_iterator;  +        typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag, +              value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;  #else          // workaround for broken reverse_iterator implementations          typedef std::reverse_iterator<iterator,T> reverse_iterator; @@ -158,7 +169,8 @@ namespace boost {          }          // assign one value to all elements -        void assign (const T& value) +        void assign (const T& value) { fill ( value ); }	// A synonym for fill +        void fill   (const T& value)          {              std::fill_n(begin(),size(),value);          } @@ -166,7 +178,8 @@ namespace boost {          // check range (may be private because it is static)          static void rangecheck (size_type i) {              if (i >= size()) { -                throw std::out_of_range("array<>: index out of range"); +                std::out_of_range e("array<>: index out of range"); +                boost::throw_exception(e);              }          } @@ -202,6 +215,11 @@ namespace boost {                                        reference, iterator, reference> > reverse_iterator;          typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,                                        const_reference, iterator, reference> > const_reverse_iterator; +#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)  +        typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,  +              value_type, reference, iterator, difference_type> reverse_iterator;  +        typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag, +              value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;  #else          // workaround for broken reverse_iterator implementations          typedef std::reverse_iterator<iterator,T> reverse_iterator; @@ -276,12 +294,14 @@ namespace boost {          }          // assign one value to all elements -        void assign (const T& ) {   } - +        void assign (const T& value) { fill ( value ); } +		void fill   (const T& ) {} +		          // check range (may be private because it is static)          static reference failed_rangecheck () {                  std::out_of_range e("attempt to access element of an empty array");                  boost::throw_exception(e); +#if defined(BOOST_NO_EXCEPTIONS) || !defined(BOOST_MSVC)                  //                  // We need to return something here to keep                  // some compilers happy: however we will never @@ -289,6 +309,7 @@ namespace boost {                  //                  static T placeholder;                  return placeholder; +#endif              }      };  #endif diff --git a/3rdParty/Boost/src/boost/asio/basic_socket_streambuf.hpp b/3rdParty/Boost/src/boost/asio/basic_socket_streambuf.hpp index 9e96401..695e8e1 100644 --- a/3rdParty/Boost/src/boost/asio/basic_socket_streambuf.hpp +++ b/3rdParty/Boost/src/boost/asio/basic_socket_streambuf.hpp @@ -50,7 +50,8 @@  //     init_buffers();  //     boost::system::error_code ec;  //     this->basic_socket<Protocol, StreamSocketService>::close(ec); -//     typedef typename Protocol::resolver_query resolver_query; +//     typedef typename Protocol::resolver resolver_type; +//     typedef typename resolver_type::query resolver_query;  //     resolver_query query(x1, ..., xn);  //     resolve_and_connect(query, ec);  //     return !ec ? this : 0; @@ -65,7 +66,8 @@      init_buffers(); \      boost::system::error_code ec; \      this->basic_socket<Protocol, StreamSocketService>::close(ec); \ -    typedef typename Protocol::resolver_query resolver_query; \ +    typedef typename Protocol::resolver resolver_type; \ +    typedef typename resolver_type::query resolver_query; \      resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \      resolve_and_connect(query, ec); \      return !ec ? this : 0; \ @@ -259,7 +261,7 @@ private:        boost::system::error_code& ec)    {      typedef typename Protocol::resolver resolver_type; -    typedef typename Protocol::resolver_iterator iterator_type; +    typedef typename resolver_type::iterator iterator_type;      resolver_type resolver(          boost::base_from_member<boost::asio::io_service>::member);      iterator_type i = resolver.resolve(query, ec); diff --git a/3rdParty/Boost/src/boost/asio/buffers_iterator.hpp b/3rdParty/Boost/src/boost/asio/buffers_iterator.hpp index 0d29213..0b654b8 100644 --- a/3rdParty/Boost/src/boost/asio/buffers_iterator.hpp +++ b/3rdParty/Boost/src/boost/asio/buffers_iterator.hpp @@ -22,7 +22,7 @@  #include <boost/assert.hpp>  #include <boost/config.hpp>  #include <boost/detail/workaround.hpp> -#include <boost/iterator/iterator_facade.hpp> +#include <boost/iterator.hpp>  #include <boost/type_traits/is_convertible.hpp>  #include <boost/type_traits/add_const.hpp>  #include <boost/asio/detail/pop_options.hpp> @@ -76,11 +76,10 @@ namespace detail  /// A random access iterator over the bytes in a buffer sequence.  template <typename BufferSequence, typename ByteType = char>  class buffers_iterator -  : public boost::iterator_facade< -        buffers_iterator<BufferSequence, ByteType>, -        typename detail::buffers_iterator_types< -          BufferSequence, ByteType>::byte_type, -        boost::random_access_traversal_tag> +  : public boost::iterator< +      std::random_access_iterator_tag, +      typename detail::buffers_iterator_types< +        BufferSequence, ByteType>::byte_type>  {  private:    typedef typename detail::buffers_iterator_types< @@ -139,9 +138,132 @@ public:      return new_iter;    } -private: -  friend class boost::iterator_core_access; +  /// Dereference an iterator. +  byte_type& operator*() const +  { +    return dereference(); +  } + +  /// Dereference an iterator. +  byte_type* operator->() const +  { +    return &dereference(); +  } + +  /// Access an individual element. +  byte_type& operator[](std::ptrdiff_t difference) const +  { +    buffers_iterator tmp(*this); +    tmp.advance(difference); +    return *tmp; +  } + +  /// Increment operator (prefix). +  buffers_iterator& operator++() +  { +    increment(); +    return *this; +  } + +  /// Increment operator (postfix). +  buffers_iterator operator++(int) +  { +    buffers_iterator tmp(*this); +    ++*this; +    return tmp; +  } + +  /// Decrement operator (prefix). +  buffers_iterator& operator--() +  { +    decrement(); +    return *this; +  } + +  /// Decrement operator (postfix). +  buffers_iterator operator--(int) +  { +    buffers_iterator tmp(*this); +    --*this; +    return tmp; +  } +  /// Addition operator. +  buffers_iterator& operator+=(std::ptrdiff_t difference) +  { +    advance(difference); +    return *this; +  } + +  /// Subtraction operator. +  buffers_iterator& operator-=(std::ptrdiff_t difference) +  { +    advance(-difference); +    return *this; +  } + +  /// Addition operator. +  friend buffers_iterator operator+(const buffers_iterator& iter, +      std::ptrdiff_t difference) +  { +    buffers_iterator tmp(iter); +    tmp.advance(difference); +    return tmp; +  } + +  /// Subtraction operator. +  friend buffers_iterator operator-(const buffers_iterator& iter, +      std::ptrdiff_t difference) +  { +    buffers_iterator tmp(iter); +    tmp.advance(-difference); +    return tmp; +  } + +  /// Subtraction operator. +  friend std::ptrdiff_t operator-(const buffers_iterator& a, +      const buffers_iterator& b) +  { +    return b.distance_to(a); +  } + +  /// Test two iterators for equality. +  friend bool operator==(const buffers_iterator& a, const buffers_iterator& b) +  { +    return a.equal(b); +  } + +  /// Test two iterators for inequality. +  friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b) +  { +    return !a.equal(b); +  } + +  /// Compare two iterators. +  friend bool operator<(const buffers_iterator& a, const buffers_iterator& b) +  { +    return a.distance_to(b) > 0; +  } + +  /// Compare two iterators. +  friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b) +  { +    return !(b < a); +  } + +  /// Compare two iterators. +  friend bool operator>(const buffers_iterator& a, const buffers_iterator& b) +  { +    return b < a; +  } + +  /// Compare two iterators. +  friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b) +  { +    return !(a < b); +  } + +private:    // Dereference the iterator.    byte_type& dereference() const    { diff --git a/3rdParty/Boost/src/boost/asio/datagram_socket_service.hpp b/3rdParty/Boost/src/boost/asio/datagram_socket_service.hpp index 93deddc..74bf703 100644 --- a/3rdParty/Boost/src/boost/asio/datagram_socket_service.hpp +++ b/3rdParty/Boost/src/boost/asio/datagram_socket_service.hpp @@ -28,17 +28,7 @@  #if defined(BOOST_ASIO_HAS_IOCP)  # include <boost/asio/detail/win_iocp_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include <boost/asio/detail/epoll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include <boost/asio/detail/kqueue_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include <boost/asio/detail/dev_poll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp>  #else -# include <boost/asio/detail/select_reactor.hpp>  # include <boost/asio/detail/reactive_socket_service.hpp>  #endif @@ -70,18 +60,8 @@ private:    // The type of the platform-specific implementation.  #if defined(BOOST_ASIO_HAS_IOCP)    typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::reactive_socket_service< -      Protocol, detail::epoll_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::reactive_socket_service< -      Protocol, detail::kqueue_reactor<false> > service_impl_type; -#elif defined(BOOST_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; +  typedef detail::reactive_socket_service<Protocol> service_impl_type;  #endif  public: @@ -103,13 +83,14 @@ public:    explicit datagram_socket_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<          datagram_socket_service<Protocol> >(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new datagram socket implementation. @@ -324,8 +305,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace asio diff --git a/3rdParty/Boost/src/boost/asio/deadline_timer_service.hpp b/3rdParty/Boost/src/boost/asio/deadline_timer_service.hpp index 90e7482..624791d 100644 --- a/3rdParty/Boost/src/boost/asio/deadline_timer_service.hpp +++ b/3rdParty/Boost/src/boost/asio/deadline_timer_service.hpp @@ -27,18 +27,6 @@  #include <boost/asio/detail/deadline_timer_service.hpp>  #include <boost/asio/detail/service_base.hpp> -#if defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_io_service.hpp> -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include <boost/asio/detail/epoll_reactor.hpp> -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include <boost/asio/detail/kqueue_reactor.hpp> -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include <boost/asio/detail/dev_poll_reactor.hpp> -#else -# include <boost/asio/detail/select_reactor.hpp> -#endif -  namespace boost {  namespace asio { @@ -70,22 +58,7 @@ public:  private:    // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_IOCP) -  typedef detail::deadline_timer_service< -    traits_type, detail::win_iocp_io_service> service_impl_type; -#elif defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::deadline_timer_service< -    traits_type, detail::epoll_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::deadline_timer_service< -    traits_type, detail::kqueue_reactor<false> > service_impl_type; -#elif defined(BOOST_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; -#endif +  typedef detail::deadline_timer_service<traits_type> service_impl_type;  public:    /// The implementation type of the deadline timer. @@ -99,13 +72,14 @@ public:    explicit deadline_timer_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<          deadline_timer_service<TimeType, TimeTraits> >(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new timer implementation. @@ -166,8 +140,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace asio diff --git a/3rdParty/Boost/src/boost/asio/detail/base_from_completion_cond.hpp b/3rdParty/Boost/src/boost/asio/detail/base_from_completion_cond.hpp new file mode 100644 index 0000000..1b1f142 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/base_from_completion_cond.hpp @@ -0,0 +1,67 @@ +// +// base_from_completion_cond.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP +#define BOOST_ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/completion_condition.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename CompletionCondition> +class base_from_completion_cond +{ +protected: +  explicit base_from_completion_cond(CompletionCondition completion_condition) +    : completion_condition_(completion_condition) +  { +  } + +  std::size_t check(const boost::system::error_code& ec, +      std::size_t total_transferred) +  { +    return detail::adapt_completion_condition_result( +        completion_condition_(ec, total_transferred)); +  } + +private: +  CompletionCondition completion_condition_; +}; + +template <> +class base_from_completion_cond<transfer_all_t> +{ +protected: +  explicit base_from_completion_cond(transfer_all_t) +  { +  } + +  static std::size_t check(const boost::system::error_code& ec, +      std::size_t total_transferred) +  { +    return transfer_all_t()(ec, total_transferred); +  } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/buffer_sequence_adapter.hpp b/3rdParty/Boost/src/boost/asio/detail/buffer_sequence_adapter.hpp new file mode 100644 index 0000000..ce9652e --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/buffer_sequence_adapter.hpp @@ -0,0 +1,254 @@ +// +// buffer_sequence_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP +#define BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/buffer.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class buffer_sequence_adapter_base +{ +protected: +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +  typedef WSABUF native_buffer_type; + +  static void init_native_buffer(WSABUF& buf, +      const boost::asio::mutable_buffer& buffer) +  { +    buf.buf = boost::asio::buffer_cast<char*>(buffer); +    buf.len = boost::asio::buffer_size(buffer); +  } + +  static void init_native_buffer(WSABUF& buf, +      const boost::asio::const_buffer& buffer) +  { +    buf.buf = const_cast<char*>(boost::asio::buffer_cast<const char*>(buffer)); +    buf.len = boost::asio::buffer_size(buffer); +  } +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +  typedef iovec native_buffer_type; + +  static void init_iov_base(void*& base, void* addr) +  { +    base = addr; +  } + +  template <typename T> +  static void init_iov_base(T& base, void* addr) +  { +    base = static_cast<T>(addr); +  } + +  static void init_native_buffer(iovec& iov, +      const boost::asio::mutable_buffer& buffer) +  { +    init_iov_base(iov.iov_base, boost::asio::buffer_cast<void*>(buffer)); +    iov.iov_len = boost::asio::buffer_size(buffer); +  } + +  static void init_native_buffer(iovec& iov, +      const boost::asio::const_buffer& buffer) +  { +    init_iov_base(iov.iov_base, const_cast<void*>( +          boost::asio::buffer_cast<const void*>(buffer))); +    iov.iov_len = boost::asio::buffer_size(buffer); +  } +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +}; + +// Helper class to translate buffers into the native buffer representation. +template <typename Buffer, typename Buffers> +class buffer_sequence_adapter +  : buffer_sequence_adapter_base +{ +public: +  explicit buffer_sequence_adapter(const Buffers& buffers) +    : count_(0), total_buffer_size_(0) +  { +    typename Buffers::const_iterator iter = buffers.begin(); +    typename Buffers::const_iterator end = buffers.end(); +    for (; iter != end && count_ < max_buffers; ++iter, ++count_) +    { +      Buffer buffer(*iter); +      init_native_buffer(buffers_[count_], buffer); +      total_buffer_size_ += boost::asio::buffer_size(buffer); +    } +  } + +  native_buffer_type* buffers() +  { +    return buffers_; +  } + +  std::size_t count() const +  { +    return count_; +  } + +  bool all_empty() const +  { +    return total_buffer_size_ == 0; +  } + +  static bool all_empty(const Buffers& buffers) +  { +    typename Buffers::const_iterator iter = buffers.begin(); +    typename Buffers::const_iterator end = buffers.end(); +    std::size_t i = 0; +    for (; iter != end && i < max_buffers; ++iter, ++i) +      if (boost::asio::buffer_size(Buffer(*iter)) > 0) +        return false; +    return true; +  } + +  static void validate(const Buffers& buffers) +  { +    typename Buffers::const_iterator iter = buffers.begin(); +    typename Buffers::const_iterator end = buffers.end(); +    for (; iter != end; ++iter) +    { +      Buffer buffer(*iter); +      boost::asio::buffer_cast<const void*>(buffer); +    } +  } + +  static Buffer first(const Buffers& buffers) +  { +    typename Buffers::const_iterator iter = buffers.begin(); +    typename Buffers::const_iterator end = buffers.end(); +    for (; iter != end; ++iter) +    { +      Buffer buffer(*iter); +      if (boost::asio::buffer_size(buffer) != 0) +        return buffer; +    } +    return Buffer(); +  } + +private: +  // The maximum number of buffers to support in a single operation. +  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + +  native_buffer_type buffers_[max_buffers]; +  std::size_t count_; +  std::size_t total_buffer_size_; +}; + +template <typename Buffer> +class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1> +  : buffer_sequence_adapter_base +{ +public: +  explicit buffer_sequence_adapter( +      const boost::asio::mutable_buffers_1& buffers) +  { +    init_native_buffer(buffer_, buffers); +    total_buffer_size_ = boost::asio::buffer_size(buffers); +  } + +  native_buffer_type* buffers() +  { +    return &buffer_; +  } + +  std::size_t count() const +  { +    return 1; +  } + +  bool all_empty() const +  { +    return total_buffer_size_ == 0; +  } + +  static bool all_empty(const boost::asio::mutable_buffers_1& buffers) +  { +    return boost::asio::buffer_size(buffers) == 0; +  } + +  static void validate(const boost::asio::mutable_buffers_1& buffers) +  { +    boost::asio::buffer_cast<const void*>(buffers); +  } + +  static Buffer first(const boost::asio::mutable_buffers_1& buffers) +  { +    return Buffer(buffers); +  } + +private: +  native_buffer_type buffer_; +  std::size_t total_buffer_size_; +}; + +template <typename Buffer> +class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1> +  : buffer_sequence_adapter_base +{ +public: +  explicit buffer_sequence_adapter( +      const boost::asio::const_buffers_1& buffers) +  { +    init_native_buffer(buffer_, buffers); +    total_buffer_size_ = boost::asio::buffer_size(buffers); +  } + +  native_buffer_type* buffers() +  { +    return &buffer_; +  } + +  std::size_t count() const +  { +    return 1; +  } + +  bool all_empty() const +  { +    return total_buffer_size_ == 0; +  } + +  static bool all_empty(const boost::asio::const_buffers_1& buffers) +  { +    return boost::asio::buffer_size(buffers) == 0; +  } + +  static void validate(const boost::asio::const_buffers_1& buffers) +  { +    boost::asio::buffer_cast<const void*>(buffers); +  } + +  static Buffer first(const boost::asio::const_buffers_1& buffers) +  { +    return Buffer(buffers); +  } + +private: +  native_buffer_type buffer_; +  std::size_t total_buffer_size_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/completion_handler.hpp b/3rdParty/Boost/src/boost/asio/detail/completion_handler.hpp new file mode 100644 index 0000000..d78e6c8 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/completion_handler.hpp @@ -0,0 +1,73 @@ +// +// completion_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_COMPLETION_HANDLER_HPP +#define BOOST_ASIO_DETAIL_COMPLETION_HANDLER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/fenced_block.hpp> +#include <boost/asio/detail/handler_alloc_helpers.hpp> +#include <boost/asio/detail/handler_invoke_helpers.hpp> +#include <boost/asio/detail/operation.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Handler> +class completion_handler : public operation +{ +public: +  completion_handler(Handler h) +    : operation(&completion_handler::do_complete), +      handler_(h) +  { +  } + +  static void do_complete(io_service_impl* owner, operation* base, +      boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) +  { +    // Take ownership of the handler object. +    completion_handler* h(static_cast<completion_handler*>(base)); +    typedef handler_alloc_traits<Handler, completion_handler> alloc_traits; +    handler_ptr<alloc_traits> ptr(h->handler_, h); + +    // Make the upcall if required. +    if (owner) +    { +      // 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. +      Handler handler(h->handler_); +      ptr.reset(); +      boost::asio::detail::fenced_block b; +      boost_asio_handler_invoke_helpers::invoke(handler, handler); +    } +  } + +private: +  Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_COMPLETION_HANDLER_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/consuming_buffers.hpp b/3rdParty/Boost/src/boost/asio/detail/consuming_buffers.hpp index bf04b1b..3604cba 100644 --- a/3rdParty/Boost/src/boost/asio/detail/consuming_buffers.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/consuming_buffers.hpp @@ -21,12 +21,11 @@  #include <algorithm>  #include <cstddef>  #include <boost/config.hpp> -#include <boost/iterator/iterator_facade.hpp> +#include <boost/iterator.hpp>  #include <boost/limits.hpp>  #include <boost/asio/detail/pop_options.hpp>  #include <boost/asio/buffer.hpp> -#include <boost/asio/completion_condition.hpp>  namespace boost {  namespace asio { @@ -35,9 +34,7 @@ namespace detail {  // A proxy iterator for a sub-range in a list of buffers.  template <typename Buffer, typename Buffer_Iterator>  class consuming_buffers_iterator -  : public boost::iterator_facade< -        consuming_buffers_iterator<Buffer, Buffer_Iterator>, -        const Buffer, boost::forward_traversal_tag> +  : public boost::iterator<std::forward_iterator_tag, const Buffer>  {  public:    // Default constructor creates an end iterator. @@ -60,9 +57,48 @@ public:    {    } -private: -  friend class boost::iterator_core_access; +  // Dereference an iterator. +  const Buffer& operator*() const +  { +    return dereference(); +  } + +  // Dereference an iterator. +  const Buffer* operator->() const +  { +    return &dereference(); +  } + +  // Increment operator (prefix). +  consuming_buffers_iterator& operator++() +  { +    increment(); +    return *this; +  } +  // Increment operator (postfix). +  consuming_buffers_iterator operator++(int) +  { +    consuming_buffers_iterator tmp(*this); +    ++*this; +    return tmp; +  } + +  // Test two iterators for equality. +  friend bool operator==(const consuming_buffers_iterator& a, +      const consuming_buffers_iterator& b) +  { +    return a.equal(b); +  } + +  // Test two iterators for inequality. +  friend bool operator!=(const consuming_buffers_iterator& a, +      const consuming_buffers_iterator& b) +  { +    return !a.equal(b); +  } + +private:    void increment()    {      if (!at_end_) @@ -170,7 +206,7 @@ public:    }    // Set the maximum size for a single transfer. -  void set_max_size(std::size_t max_size) +  void prepare(std::size_t max_size)    {      max_size_ = max_size;    } @@ -226,7 +262,7 @@ public:      // No-op.    } -  void set_max_size(std::size_t) +  void prepare(std::size_t)    {      // No-op.    } diff --git a/3rdParty/Boost/src/boost/asio/detail/deadline_timer_service.hpp b/3rdParty/Boost/src/boost/asio/detail/deadline_timer_service.hpp index 7885c9a..5ba21b1 100644 --- a/3rdParty/Boost/src/boost/asio/detail/deadline_timer_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/deadline_timer_service.hpp @@ -26,21 +26,20 @@  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp>  #include <boost/asio/detail/bind_handler.hpp> -#include <boost/asio/detail/handler_base_from_member.hpp> +#include <boost/asio/detail/fenced_block.hpp>  #include <boost/asio/detail/noncopyable.hpp> -#include <boost/asio/detail/service_base.hpp>  #include <boost/asio/detail/socket_ops.hpp>  #include <boost/asio/detail/socket_types.hpp> +#include <boost/asio/detail/timer_op.hpp>  #include <boost/asio/detail/timer_queue.hpp> +#include <boost/asio/detail/timer_scheduler.hpp>  namespace boost {  namespace asio {  namespace detail { -template <typename Time_Traits, typename Timer_Scheduler> +template <typename Time_Traits>  class deadline_timer_service -  : public boost::asio::detail::service_base< -      deadline_timer_service<Time_Traits, Timer_Scheduler> >  {  public:    // The time type. @@ -60,9 +59,7 @@ public:    // Constructor.    deadline_timer_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service), -      scheduler_(boost::asio::use_service<Timer_Scheduler>(io_service)) +    : scheduler_(boost::asio::use_service<timer_scheduler>(io_service))    {      scheduler_.init_task();      scheduler_.add_timer_queue(timer_queue_); @@ -156,34 +153,58 @@ public:    }    template <typename Handler> -  class wait_handler :  -    public handler_base_from_member<Handler> +  class wait_handler : public timer_op    {    public: -    wait_handler(boost::asio::io_service& io_service, Handler handler) -      : handler_base_from_member<Handler>(handler), -        io_service_(io_service), -        work_(io_service) +    wait_handler(Handler handler) +      : timer_op(&wait_handler::do_complete), +        handler_(handler)      {      } -    void operator()(const boost::system::error_code& result) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)      { -      io_service_.post(detail::bind_handler(this->handler_, result)); +      // Take ownership of the handler object. +      wait_handler* h(static_cast<wait_handler*>(base)); +      typedef handler_alloc_traits<Handler, wait_handler> alloc_traits; +      handler_ptr<alloc_traits> ptr(h->handler_, h); + +      // Make the upcall if required. +      if (owner) +      { +        // 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::binder1<Handler, boost::system::error_code> +          handler(h->handler_, h->ec_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      }    private: -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_; +    Handler handler_;    };    // Start an asynchronous wait on the timer.    template <typename Handler>    void async_wait(implementation_type& impl, Handler handler)    { +    // Allocate and construct an operation to wrap the handler. +    typedef wait_handler<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); +      impl.might_have_pending_waits = true; -    scheduler_.schedule_timer(timer_queue_, impl.expiry, -        wait_handler<Handler>(this->get_io_service(), handler), &impl); + +    scheduler_.schedule_timer(timer_queue_, impl.expiry, ptr.get(), &impl); +    ptr.release();    }  private: @@ -191,7 +212,7 @@ private:    timer_queue<Time_Traits> timer_queue_;    // The object that schedules and executes timers. Usually a reactor. -  Timer_Scheduler& scheduler_; +  timer_scheduler& scheduler_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor.hpp b/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor.hpp index 7315384..e00f501 100644 --- a/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor.hpp @@ -33,27 +33,30 @@  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp> -#include <boost/asio/detail/bind_handler.hpp>  #include <boost/asio/detail/hash_map.hpp>  #include <boost/asio/detail/mutex.hpp> -#include <boost/asio/detail/task_io_service.hpp> -#include <boost/asio/detail/thread.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/reactor_op.hpp>  #include <boost/asio/detail/reactor_op_queue.hpp>  #include <boost/asio/detail/select_interrupter.hpp>  #include <boost/asio/detail/service_base.hpp> -#include <boost/asio/detail/signal_blocker.hpp>  #include <boost/asio/detail/socket_types.hpp> -#include <boost/asio/detail/timer_queue.hpp> +#include <boost/asio/detail/timer_op.hpp> +#include <boost/asio/detail/timer_queue_base.hpp> +#include <boost/asio/detail/timer_queue_fwd.hpp> +#include <boost/asio/detail/timer_queue_set.hpp>  namespace boost {  namespace asio {  namespace detail { -template <bool Own_Thread>  class dev_poll_reactor -  : public boost::asio::detail::service_base<dev_poll_reactor<Own_Thread> > +  : public boost::asio::detail::service_base<dev_poll_reactor>  {  public: +  enum { read_op = 0, write_op = 1, +    connect_op = 1, except_op = 2, max_ops = 3 }; +    // Per-descriptor data.    struct per_descriptor_data    { @@ -61,28 +64,13 @@ public:    // Constructor.    dev_poll_reactor(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        dev_poll_reactor<Own_Thread> >(io_service), +    : boost::asio::detail::service_base<dev_poll_reactor>(io_service), +      io_service_(use_service<io_service_impl>(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) -    { -      boost::asio::detail::signal_blocker sb; -      thread_ = new boost::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(); @@ -103,35 +91,20 @@ public:    {      boost::asio::detail::mutex::scoped_lock lock(mutex_);      shutdown_ = true; -    stop_thread_ = true;      lock.unlock(); -    if (thread_) -    { -      interrupter_.interrupt(); -      thread_->join(); -      delete thread_; -      thread_ = 0; -    } +    op_queue<operation> ops; -    read_op_queue_.destroy_operations(); -    write_op_queue_.destroy_operations(); -    except_op_queue_.destroy_operations(); +    for (int i = 0; i < max_ops; ++i) +      op_queue_[i].get_all_operations(ops); -    for (std::size_t i = 0; i < timer_queues_.size(); ++i) -      timer_queues_[i]->destroy_timers(); -    timer_queues_.clear(); +    timer_queues_.get_all_timers(ops);    }  -  // Initialise the task, but only if the reactor is not in its own thread. +  // Initialise the task.    void init_task()    { -    if (!Own_Thread) -    { -      typedef task_io_service<dev_poll_reactor<Own_Thread> > -        task_io_service_type; -      use_service<task_io_service_type>(this->get_io_service()).init_task(); -    } +    io_service_.init_task();    }    // Register a socket with the reactor. Returns 0 on success, system error @@ -141,121 +114,46 @@ public:      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, per_descriptor_data&, -      Handler handler, bool allow_speculative_read = true) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    if (shutdown_) -      return; - -    if (allow_speculative_read) -    { -      if (!read_op_queue_.has_operation(descriptor)) -      { -        boost::system::error_code ec; -        std::size_t bytes_transferred = 0; -        if (handler.perform(ec, bytes_transferred)) -        { -          handler.complete(ec, bytes_transferred); -          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, per_descriptor_data&, -      Handler handler, bool allow_speculative_write = true) +  // Start a new operation. The reactor operation will be performed when the +  // given descriptor is flagged as ready, or an error has occurred. +  void start_op(int op_type, socket_type descriptor, +      per_descriptor_data&, reactor_op* op, bool allow_speculative)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_);      if (shutdown_)        return; -    if (allow_speculative_write) +    if (allow_speculative)      { -      if (!write_op_queue_.has_operation(descriptor)) +      if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))        { -        boost::system::error_code ec; -        std::size_t bytes_transferred = 0; -        if (handler.perform(ec, bytes_transferred)) +        if (!op_queue_[op_type].has_operation(descriptor))          { -          handler.complete(ec, bytes_transferred); -          return; +          if (op->perform()) +          { +            lock.unlock(); +            io_service_.post_immediate_completion(op); +            return; +          }          }        }      } -    if (write_op_queue_.enqueue_operation(descriptor, handler)) +    bool first = op_queue_[op_type].enqueue_operation(descriptor, op); +    io_service_.work_started(); +    if (first)      {        ::pollfd& ev = add_pending_event_change(descriptor); -      ev.events = POLLOUT | POLLERR | POLLHUP; -      if (read_op_queue_.has_operation(descriptor)) +      ev.events = POLLERR | POLLHUP; +      if (op_type == read_op +          || op_queue_[read_op].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, -      per_descriptor_data&, Handler handler) -  { -    boost::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)) +      if (op_type == write_op +          || op_queue_[write_op].has_operation(descriptor))          ev.events |= POLLOUT; -      interrupter_.interrupt(); -    } -  } - -  // Start a new write operation. The handler object will be invoked when the -  // information available, or an error has occurred. -  template <typename Handler> -  void start_connect_op(socket_type descriptor, -      per_descriptor_data&, Handler handler) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    if (shutdown_) -      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)) +      if (op_type == except_op +          || op_queue_[except_op].has_operation(descriptor))          ev.events |= POLLPRI;        interrupter_.interrupt();      } @@ -267,7 +165,7 @@ public:    void cancel_ops(socket_type descriptor, per_descriptor_data&)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    cancel_ops_unlocked(descriptor); +    cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);    }    // Cancel any operations that are running against the descriptor and remove @@ -282,7 +180,7 @@ public:      interrupter_.interrupt();      // Cancel any outstanding operations associated with the descriptor. -    cancel_ops_unlocked(descriptor); +    cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);    }    // Add a new timer queue to the reactor. @@ -290,7 +188,7 @@ public:    void add_timer_queue(timer_queue<Time_Traits>& timer_queue)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    timer_queues_.push_back(&timer_queue); +    timer_queues_.insert(&timer_queue);    }    // Remove a timer queue from the reactor. @@ -298,71 +196,48 @@ public:    void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)    {      boost::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; -      } -    } +    timer_queues_.erase(&timer_queue);    } -  // 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> +  // Schedule a new operation in the given timer queue to expire at the +  // specified absolute time. +  template <typename Time_Traits>    void schedule_timer(timer_queue<Time_Traits>& timer_queue, -      const typename Time_Traits::time_type& time, Handler handler, void* token) +      const typename Time_Traits::time_type& time, timer_op* op, void* token)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_);      if (!shutdown_) -      if (timer_queue.enqueue_timer(time, handler, token)) +    { +      bool earliest = timer_queue.enqueue_timer(time, op, token); +      io_service_.work_started(); +      if (earliest)          interrupter_.interrupt(); +    }    } -  // Cancel the timer associated with the given token. Returns the number of -  // handlers that have been posted or dispatched. +  // Cancel the timer operations associated with the given token. Returns the +  // number of operations that have been posted or dispatched.    template <typename Time_Traits>    std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    std::size_t n = timer_queue.cancel_timer(token); -    if (n > 0) -      interrupter_.interrupt(); +    op_queue<operation> ops; +    std::size_t n = timer_queue.cancel_timer(token, ops); +    lock.unlock(); +    io_service_.post_deferred_completions(ops);      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) +  void run(bool block, op_queue<operation>& ops)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    // Dispatch any operation cancellations that were made while the select -    // loop was not running. -    read_op_queue_.perform_cancellations(); -    write_op_queue_.perform_cancellations(); -    except_op_queue_.perform_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_) -    { -      complete_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()) -    { -      complete_operations_and_timers(lock); +    if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty() +        && op_queue_[except_op].empty() && timer_queues_.all_empty())        return; -    }      // Write the pending event registration changes to the /dev/poll descriptor.      std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size(); @@ -373,14 +248,13 @@ private:            &pending_event_changes_[0], events_size);        if (result != static_cast<int>(events_size))        { +        boost::system::error_code ec = boost::system::error_code( +            errno, boost::asio::error::get_system_category());          for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)          {            int descriptor = pending_event_changes_[i].fd; -          boost::system::error_code ec = boost::system::error_code( -              errno, boost::asio::error::get_system_category()); -          read_op_queue_.perform_all_operations(descriptor, ec); -          write_op_queue_.perform_all_operations(descriptor, ec); -          except_op_queue_.perform_all_operations(descriptor, ec); +          for (int j = 0; j < max_ops; ++j) +            op_queue_[j].cancel_operations(descriptor, ops, ec);          }        }        pending_event_changes_.clear(); @@ -388,7 +262,6 @@ private:      }      int timeout = block ? get_timeout() : 0; -    wait_in_progress_ = true;      lock.unlock();      // Block on the /dev/poll descriptor. @@ -400,7 +273,6 @@ private:      int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);      lock.lock(); -    wait_in_progress_ = false;      // Dispatch the waiting events.      for (int i = 0; i < num_events; ++i) @@ -415,24 +287,24 @@ private:          bool more_reads = false;          bool more_writes = false;          bool more_except = false; -        boost::system::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_.perform_operation(descriptor, ec); +          more_except = +            op_queue_[except_op].perform_operations(descriptor, ops);          else -          more_except = except_op_queue_.has_operation(descriptor); +          more_except = op_queue_[except_op].has_operation(descriptor);          if (events[i].events & (POLLIN | POLLERR | POLLHUP)) -          more_reads = read_op_queue_.perform_operation(descriptor, ec); +          more_reads = op_queue_[read_op].perform_operations(descriptor, ops);          else -          more_reads = read_op_queue_.has_operation(descriptor); +          more_reads = op_queue_[read_op].has_operation(descriptor);          if (events[i].events & (POLLOUT | POLLERR | POLLHUP)) -          more_writes = write_op_queue_.perform_operation(descriptor, ec); +          more_writes = op_queue_[write_op].perform_operations(descriptor, ops);          else -          more_writes = write_op_queue_.has_operation(descriptor); +          more_writes = op_queue_[write_op].has_operation(descriptor);          if ((events[i].events & (POLLERR | POLLHUP)) != 0                && !more_except && !more_reads && !more_writes) @@ -463,48 +335,15 @@ private:            int result = ::write(dev_poll_fd_, &ev, sizeof(ev));            if (result != sizeof(ev))            { -            ec = boost::system::error_code(errno, +            boost::system::error_code ec(errno,                  boost::asio::error::get_system_category()); -            read_op_queue_.perform_all_operations(descriptor, ec); -            write_op_queue_.perform_all_operations(descriptor, ec); -            except_op_queue_.perform_all_operations(descriptor, ec); +            for (int j = 0; j < max_ops; ++j) +              op_queue_[j].cancel_operations(descriptor, ops, ec);            }          }        }      } -    read_op_queue_.perform_cancellations(); -    write_op_queue_.perform_cancellations(); -    except_op_queue_.perform_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(); - -    complete_operations_and_timers(lock); -  } - -  // Run the select loop in the thread. -  void run_thread() -  { -    boost::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(); +    timer_queues_.get_ready_timers(ops);    }    // Interrupt the select loop. @@ -513,6 +352,7 @@ private:      interrupter_.interrupt();    } +private:    // Create the /dev/poll file descriptor. Throws an exception if the descriptor    // cannot be created.    static int do_dev_poll_create() @@ -529,75 +369,32 @@ private:      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; -    } +    return timer_queues_.wait_duration_msec(5 * 60 * 1000);    }    // 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) +  void cancel_ops_unlocked(socket_type descriptor, +      const boost::system::error_code& ec)    { -    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) +    bool need_interrupt = false; +    op_queue<operation> ops; +    for (int i = 0; i < max_ops; ++i) +      need_interrupt = op_queue_[i].cancel_operations( +          descriptor, ops, ec) || need_interrupt; +    io_service_.post_deferred_completions(ops); +    if (need_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 complete_operations_and_timers( -      boost::asio::detail::mutex::scoped_lock& lock) -  { -    timer_queues_for_cleanup_ = timer_queues_; -    lock.unlock(); -    read_op_queue_.complete_operations(); -    write_op_queue_.complete_operations(); -    except_op_queue_.complete_operations(); -    for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) -      timer_queues_for_cleanup_[i]->complete_timers(); -  } -    // Add a pending event entry for the given descriptor.    ::pollfd& add_pending_event_change(int descriptor)    { @@ -619,6 +416,9 @@ private:      }    } +  // The io_service implementation used to post completions. +  io_service_impl& io_service_; +    // Mutex to protect access to internal data.    boost::asio::detail::mutex mutex_; @@ -631,36 +431,14 @@ private:    // 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 queues of read, write and except operations. +  reactor_op_queue<socket_type> op_queue_[max_ops];    // 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. -  boost::asio::detail::thread* thread_; +  timer_queue_set timer_queues_;    // Whether the service has been shut down.    bool shutdown_; diff --git a/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor_fwd.hpp b/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor_fwd.hpp index d890fa8..238cee5 100644 --- a/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor_fwd.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor_fwd.hpp @@ -27,7 +27,6 @@ namespace boost {  namespace asio {  namespace detail { -template <bool Own_Thread>  class dev_poll_reactor;  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/epoll_reactor.hpp b/3rdParty/Boost/src/boost/asio/detail/epoll_reactor.hpp index 6c6bfe3..4684944 100644 --- a/3rdParty/Boost/src/boost/asio/detail/epoll_reactor.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/epoll_reactor.hpp @@ -23,115 +23,126 @@  #include <boost/asio/detail/push_options.hpp>  #include <cstddef> -#include <vector>  #include <sys/epoll.h>  #include <boost/config.hpp> -#include <boost/date_time/posix_time/posix_time_types.hpp>  #include <boost/throw_exception.hpp>  #include <boost/system/system_error.hpp>  #include <boost/asio/detail/pop_options.hpp>  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp> -#include <boost/asio/detail/bind_handler.hpp>  #include <boost/asio/detail/hash_map.hpp>  #include <boost/asio/detail/mutex.hpp> -#include <boost/asio/detail/task_io_service.hpp> -#include <boost/asio/detail/thread.hpp> -#include <boost/asio/detail/reactor_op_queue.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/reactor_op.hpp>  #include <boost/asio/detail/select_interrupter.hpp>  #include <boost/asio/detail/service_base.hpp> -#include <boost/asio/detail/signal_blocker.hpp>  #include <boost/asio/detail/socket_types.hpp> -#include <boost/asio/detail/timer_queue.hpp> +#include <boost/asio/detail/timer_op.hpp> +#include <boost/asio/detail/timer_queue_base.hpp> +#include <boost/asio/detail/timer_queue_fwd.hpp> +#include <boost/asio/detail/timer_queue_set.hpp> + +#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# define BOOST_ASIO_HAS_TIMERFD 1 +#endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) + +#if defined(BOOST_ASIO_HAS_TIMERFD) +# include <boost/asio/detail/push_options.hpp> +# include <sys/timerfd.h> +# include <boost/asio/detail/pop_options.hpp> +#endif // defined(BOOST_ASIO_HAS_TIMERFD)  namespace boost {  namespace asio {  namespace detail { -template <bool Own_Thread>  class epoll_reactor -  : public boost::asio::detail::service_base<epoll_reactor<Own_Thread> > +  : public boost::asio::detail::service_base<epoll_reactor>  {  public: -  // Per-descriptor data. -  struct per_descriptor_data +  enum { read_op = 0, write_op = 1, +    connect_op = 1, except_op = 2, max_ops = 3 }; + +  // Per-descriptor queues. +  struct descriptor_state    { -    bool allow_speculative_read; -    bool allow_speculative_write; +    descriptor_state() {} +    descriptor_state(const descriptor_state&) {} +    void operator=(const descriptor_state&) {} + +    mutex mutex_; +    op_queue<reactor_op> op_queue_[max_ops]; +    bool shutdown_;    }; +  // Per-descriptor data. +  typedef descriptor_state* per_descriptor_data; +    // Constructor.    epoll_reactor(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base<epoll_reactor<Own_Thread> >(io_service), +    : boost::asio::detail::service_base<epoll_reactor>(io_service), +      io_service_(use_service<io_service_impl>(io_service)),        mutex_(),        epoll_fd_(do_epoll_create()), -      wait_in_progress_(false), +#if defined(BOOST_ASIO_HAS_TIMERFD) +      timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)), +#else // defined(BOOST_ASIO_HAS_TIMERFD) +      timer_fd_(-1), +#endif // defined(BOOST_ASIO_HAS_TIMERFD)        interrupter_(), -      read_op_queue_(), -      write_op_queue_(), -      except_op_queue_(), -      pending_cancellations_(), -      stop_thread_(false), -      thread_(0), -      shutdown_(false), -      need_epoll_wait_(true) +      shutdown_(false)    { -    // Start the reactor's internal thread only if needed. -    if (Own_Thread) -    { -      boost::asio::detail::signal_blocker sb; -      thread_ = new boost::asio::detail::thread( -          bind_handler(&epoll_reactor::call_run_thread, this)); -    } -      // Add the interrupter's descriptor to epoll.      epoll_event ev = { 0, { 0 } }; -    ev.events = EPOLLIN | EPOLLERR; -    ev.data.fd = interrupter_.read_descriptor(); +    ev.events = EPOLLIN | EPOLLERR | EPOLLET; +    ev.data.ptr = &interrupter_;      epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev); +    interrupter_.interrupt(); + +    // Add the timer descriptor to epoll. +    if (timer_fd_ != -1) +    { +      ev.events = EPOLLIN | EPOLLERR; +      ev.data.ptr = &timer_fd_; +      epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev); +    }    }    // Destructor.    ~epoll_reactor()    { -    shutdown_service();      close(epoll_fd_); +    if (timer_fd_ != -1) +      close(timer_fd_);    }    // Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    mutex::scoped_lock lock(mutex_);      shutdown_ = true; -    stop_thread_ = true;      lock.unlock(); -    if (thread_) +    op_queue<operation> ops; + +    descriptor_map::iterator iter = registered_descriptors_.begin(); +    descriptor_map::iterator end = registered_descriptors_.end(); +    while (iter != end)      { -      interrupter_.interrupt(); -      thread_->join(); -      delete thread_; -      thread_ = 0; +      for (int i = 0; i < max_ops; ++i) +        ops.push(iter->second.op_queue_[i]); +      iter->second.shutdown_ = true; +      ++iter;      } -    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(); +    timer_queues_.get_all_timers(ops);    } -  // Initialise the task, but only if the reactor is not in its own thread. +  // Initialise the task.    void init_task()    { -    if (!Own_Thread) -    { -      typedef task_io_service<epoll_reactor<Own_Thread> > task_io_service_type; -      use_service<task_io_service_type>(this->get_io_service()).init_task(); -    } +    io_service_.init_task();    }    // Register a socket with the reactor. Returns 0 on success, system error @@ -139,454 +150,274 @@ public:    int register_descriptor(socket_type descriptor,        per_descriptor_data& descriptor_data)    { -    // No need to lock according to epoll documentation. +    mutex::scoped_lock lock(registered_descriptors_mutex_); -    descriptor_data.allow_speculative_read = true; -    descriptor_data.allow_speculative_write = true; +    descriptor_map::iterator new_entry = registered_descriptors_.insert( +          std::make_pair(descriptor, descriptor_state())).first; +    descriptor_data = &new_entry->second;      epoll_event ev = { 0, { 0 } }; -    ev.events = 0; -    ev.data.fd = descriptor; +    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET; +    ev.data.ptr = descriptor_data;      int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);      if (result != 0)        return errno; + +    descriptor_data->shutdown_ = false; +      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, +  // Start a new operation. The reactor operation will be performed when the +  // given descriptor is flagged as ready, or an error has occurred. +  void start_op(int op_type, socket_type descriptor,        per_descriptor_data& descriptor_data, -      Handler handler, bool allow_speculative_read = true) +      reactor_op* op, bool allow_speculative)    { -    if (allow_speculative_read && descriptor_data.allow_speculative_read) -    { -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) -      { -        handler.complete(ec, bytes_transferred); -        return; -      } - -      // We only get one shot at a speculative read in this function. -      allow_speculative_read = false; -    } - -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    if (shutdown_) +    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); +    if (descriptor_data->shutdown_)        return; -    if (!allow_speculative_read) -      need_epoll_wait_ = true; -    else if (!read_op_queue_.has_operation(descriptor)) +    if (descriptor_data->op_queue_[op_type].empty())      { -      // Speculative reads are ok as there are no queued read operations. -      descriptor_data.allow_speculative_read = true; - -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) +      if (allow_speculative +          && (op_type != read_op +            || descriptor_data->op_queue_[except_op].empty()))        { -        handler.complete(ec, bytes_transferred); -        return; +        if (op->perform()) +        { +          descriptor_lock.unlock(); +          io_service_.post_immediate_completion(op); +          return; +        }        } -    } - -    // Speculative reads are not ok as there will be queued read operations. -    descriptor_data.allow_speculative_read = false; - -    if (read_op_queue_.enqueue_operation(descriptor, handler)) -    { -      epoll_event ev = { 0, { 0 } }; -      ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; -      if (write_op_queue_.has_operation(descriptor)) -        ev.events |= EPOLLOUT; -      if (except_op_queue_.has_operation(descriptor)) -        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) +      else        { -        boost::system::error_code ec(errno, -            boost::asio::error::get_system_category()); -        read_op_queue_.perform_all_operations(descriptor, ec); +        epoll_event ev = { 0, { 0 } }; +        ev.events = EPOLLIN | EPOLLERR | EPOLLHUP +          | EPOLLOUT | EPOLLPRI | EPOLLET; +        ev.data.ptr = descriptor_data; +        epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);        }      } + +    descriptor_data->op_queue_[op_type].push(op); +    io_service_.work_started();    } -  // 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, -      per_descriptor_data& descriptor_data, -      Handler handler, bool allow_speculative_write = true) +  // 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, per_descriptor_data& descriptor_data)    { -    if (allow_speculative_write && descriptor_data.allow_speculative_write) -    { -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) -      { -        handler.complete(ec, bytes_transferred); -        return; -      } - -      // We only get one shot at a speculative write in this function. -      allow_speculative_write = false; -    } - -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); -    if (shutdown_) -      return; - -    if (!allow_speculative_write) -      need_epoll_wait_ = true; -    else if (!write_op_queue_.has_operation(descriptor)) +    op_queue<operation> ops; +    for (int i = 0; i < max_ops; ++i)      { -      // Speculative writes are ok as there are no queued write operations. -      descriptor_data.allow_speculative_write = true; - -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) +      while (reactor_op* op = descriptor_data->op_queue_[i].front())        { -        handler.complete(ec, bytes_transferred); -        return; +        op->ec_ = boost::asio::error::operation_aborted; +        descriptor_data->op_queue_[i].pop(); +        ops.push(op);        }      } -    // Speculative writes are not ok as there will be queued write operations. -    descriptor_data.allow_speculative_write = false; +    descriptor_lock.unlock(); -    if (write_op_queue_.enqueue_operation(descriptor, handler)) -    { -      epoll_event ev = { 0, { 0 } }; -      ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; -      if (read_op_queue_.has_operation(descriptor)) -        ev.events |= EPOLLIN; -      if (except_op_queue_.has_operation(descriptor)) -        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) -      { -        boost::system::error_code ec(errno, -            boost::asio::error::get_system_category()); -        write_op_queue_.perform_all_operations(descriptor, ec); -      } -    } +    io_service_.post_deferred_completions(ops);    } -  // 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, -      per_descriptor_data&, Handler handler) +  // Cancel any operations that are running against the descriptor and remove +  // its registration from the reactor. +  void close_descriptor(socket_type descriptor, +      per_descriptor_data& descriptor_data)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); +    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); -    if (shutdown_) -      return; +    // Remove the descriptor from the set of known descriptors. The descriptor +    // will be automatically removed from the epoll set when it is closed. +    descriptor_data->shutdown_ = true; -    if (except_op_queue_.enqueue_operation(descriptor, handler)) +    op_queue<operation> ops; +    for (int i = 0; i < max_ops; ++i)      { -      epoll_event ev = { 0, { 0 } }; -      ev.events = EPOLLPRI | EPOLLERR | EPOLLHUP; -      if (read_op_queue_.has_operation(descriptor)) -        ev.events |= EPOLLIN; -      if (write_op_queue_.has_operation(descriptor)) -        ev.events |= EPOLLOUT; -      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) +      while (reactor_op* op = descriptor_data->op_queue_[i].front())        { -        boost::system::error_code ec(errno, -            boost::asio::error::get_system_category()); -        except_op_queue_.perform_all_operations(descriptor, ec); +        op->ec_ = boost::asio::error::operation_aborted; +        descriptor_data->op_queue_[i].pop(); +        ops.push(op);        }      } -  } -  // Start a new write operation. The handler object will be invoked when the -  // given descriptor is ready for writing or an error has occurred. Speculative -  // writes are not allowed. -  template <typename Handler> -  void start_connect_op(socket_type descriptor, -      per_descriptor_data& descriptor_data, Handler handler) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    descriptor_lock.unlock(); -    if (shutdown_) -      return; +    registered_descriptors_.erase(descriptor); -    // Speculative writes are not ok as there will be queued write operations. -    descriptor_data.allow_speculative_write = false; - -    if (write_op_queue_.enqueue_operation(descriptor, handler)) -    { -      epoll_event ev = { 0, { 0 } }; -      ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; -      if (read_op_queue_.has_operation(descriptor)) -        ev.events |= EPOLLIN; -      if (except_op_queue_.has_operation(descriptor)) -        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) -      { -        boost::system::error_code ec(errno, -            boost::asio::error::get_system_category()); -        write_op_queue_.perform_all_operations(descriptor, ec); -      } -    } -  } +    descriptors_lock.unlock(); -  // 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, per_descriptor_data&) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    cancel_ops_unlocked(descriptor); -  } - -  // Cancel any operations that are running against the descriptor and remove -  // its registration from the reactor. -  void close_descriptor(socket_type descriptor, per_descriptor_data&) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    // Remove the descriptor from epoll. -    epoll_event ev = { 0, { 0 } }; -    epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); - -    // Cancel any outstanding operations associated with the descriptor. -    cancel_ops_unlocked(descriptor); +    io_service_.post_deferred_completions(ops);    }    // Add a new timer queue to the reactor.    template <typename Time_Traits>    void add_timer_queue(timer_queue<Time_Traits>& timer_queue)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    timer_queues_.push_back(&timer_queue); +    mutex::scoped_lock lock(mutex_); +    timer_queues_.insert(&timer_queue);    }    // Remove a timer queue from the reactor.    template <typename Time_Traits>    void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)    { -    boost::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; -      } -    } +    mutex::scoped_lock lock(mutex_); +    timer_queues_.erase(&timer_queue);    } -  // 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> +  // Schedule a new operation in the given timer queue to expire at the +  // specified absolute time. +  template <typename Time_Traits>    void schedule_timer(timer_queue<Time_Traits>& timer_queue, -      const typename Time_Traits::time_type& time, Handler handler, void* token) +      const typename Time_Traits::time_type& time, timer_op* op, void* token)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    mutex::scoped_lock lock(mutex_);      if (!shutdown_) -      if (timer_queue.enqueue_timer(time, handler, token)) +    { +      bool earliest = timer_queue.enqueue_timer(time, op, token); +      io_service_.work_started(); +      if (earliest) +      { +#if defined(BOOST_ASIO_HAS_TIMERFD) +        if (timer_fd_ != -1) +        { +          itimerspec new_timeout; +          itimerspec old_timeout; +          int flags = get_timeout(new_timeout); +          timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout); +          return; +        } +#endif // defined(BOOST_ASIO_HAS_TIMERFD)          interrupter_.interrupt(); +      } +    }    } -  // Cancel the timer associated with the given token. Returns the number of -  // handlers that have been posted or dispatched. +  // Cancel the timer operations associated with the given token. Returns the +  // number of operations that have been posted or dispatched.    template <typename Time_Traits>    std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    std::size_t n = timer_queue.cancel_timer(token); -    if (n > 0) -      interrupter_.interrupt(); +    mutex::scoped_lock lock(mutex_); +    op_queue<operation> ops; +    std::size_t n = timer_queue.cancel_timer(token, ops); +    lock.unlock(); +    io_service_.post_deferred_completions(ops);      return n;    } -private: -  friend class task_io_service<epoll_reactor<Own_Thread> >; -    // Run epoll once until interrupted or events are ready to be dispatched. -  void run(bool block) +  void run(bool block, op_queue<operation>& ops)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    // Dispatch any operation cancellations that were made while the select -    // loop was not running. -    read_op_queue_.perform_cancellations(); -    write_op_queue_.perform_cancellations(); -    except_op_queue_.perform_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_) -    { -      complete_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()) +    // Calculate a timeout only if timerfd is not used. +    int timeout; +    if (timer_fd_ != -1) +      timeout = block ? -1 : 0; +    else      { -      complete_operations_and_timers(lock); -      return; +      mutex::scoped_lock lock(mutex_); +      timeout = block ? get_timeout() : 0;      } -    int timeout = block ? get_timeout() : 0; -    wait_in_progress_ = true; -    lock.unlock(); -      // Block on the epoll descriptor.      epoll_event events[128]; -    int num_events = (block || need_epoll_wait_) -      ? epoll_wait(epoll_fd_, events, 128, timeout) -      : 0; +    int num_events = epoll_wait(epoll_fd_, events, 128, timeout); -    lock.lock(); -    wait_in_progress_ = false; +#if defined(BOOST_ASIO_HAS_TIMERFD) +    bool check_timers = (timer_fd_ == -1); +#else // defined(BOOST_ASIO_HAS_TIMERFD) +    bool check_timers = true; +#endif // defined(BOOST_ASIO_HAS_TIMERFD)      // Dispatch the waiting events.      for (int i = 0; i < num_events; ++i)      { -      int descriptor = events[i].data.fd; -      if (descriptor == interrupter_.read_descriptor()) +      void* ptr = events[i].data.ptr; +      if (ptr == &interrupter_)        { -        interrupter_.reset(); +        // No need to reset the interrupter since we're leaving the descriptor +        // in a ready-to-read state and relying on edge-triggered notifications +        // to make it so that we only get woken up when the descriptor's epoll +        // registration is updated. + +#if defined(BOOST_ASIO_HAS_TIMERFD) +        if (timer_fd_ == -1) +          check_timers = true; +#else // defined(BOOST_ASIO_HAS_TIMERFD) +        check_timers = true; +#endif // defined(BOOST_ASIO_HAS_TIMERFD)        } +#if defined(BOOST_ASIO_HAS_TIMERFD) +      else if (ptr == &timer_fd_) +      { +        check_timers = true; +      } +#endif // defined(BOOST_ASIO_HAS_TIMERFD)        else        { -        bool more_reads = false; -        bool more_writes = false; -        bool more_except = false; -        boost::system::error_code ec; +        descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr); +        mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);          // Exception operations must be processed first to ensure that any          // out-of-band data is read before normal data. -        if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)) -          more_except = except_op_queue_.perform_operation(descriptor, ec); -        else -          more_except = except_op_queue_.has_operation(descriptor); - -        if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) -          more_reads = read_op_queue_.perform_operation(descriptor, ec); -        else -          more_reads = read_op_queue_.has_operation(descriptor); - -        if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) -          more_writes = write_op_queue_.perform_operation(descriptor, ec); -        else -          more_writes = write_op_queue_.has_operation(descriptor); - -        if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0 -              && (events[i].events & ~(EPOLLERR | EPOLLHUP)) == 0 -              && !more_except && !more_reads && !more_writes) +        static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI }; +        for (int j = max_ops - 1; j >= 0; --j)          { -          // If we have an event and no operations associated with the -          // descriptor then we need to delete the descriptor from epoll. The -          // epoll_wait system call can produce EPOLLHUP or EPOLLERR events -          // when there is no operation pending, 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) +          if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))            { -            ec = boost::system::error_code(errno, -                boost::asio::error::get_system_category()); -            read_op_queue_.perform_all_operations(descriptor, ec); -            write_op_queue_.perform_all_operations(descriptor, ec); -            except_op_queue_.perform_all_operations(descriptor, ec); +            while (reactor_op* op = descriptor_data->op_queue_[j].front()) +            { +              if (op->perform()) +              { +                descriptor_data->op_queue_[j].pop(); +                ops.push(op); +              } +              else +                break; +            }            }          }        }      } -    read_op_queue_.perform_cancellations(); -    write_op_queue_.perform_cancellations(); -    except_op_queue_.perform_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(); - -    // Determine whether epoll_wait should be called when the reactor next runs. -    need_epoll_wait_ = !read_op_queue_.empty() -      || !write_op_queue_.empty() || !except_op_queue_.empty(); - -    complete_operations_and_timers(lock); -  } -  // Run the select loop in the thread. -  void run_thread() -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    while (!stop_thread_) +    if (check_timers)      { -      lock.unlock(); -      run(true); -      lock.lock(); -    } -  } +      mutex::scoped_lock common_lock(mutex_); +      timer_queues_.get_ready_timers(ops); -  // Entry point for the select loop thread. -  static void call_run_thread(epoll_reactor* reactor) -  { -    reactor->run_thread(); +#if defined(BOOST_ASIO_HAS_TIMERFD) +      if (timer_fd_ != -1) +      { +        itimerspec new_timeout; +        itimerspec old_timeout; +        int flags = get_timeout(new_timeout); +        timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout); +      } +#endif // defined(BOOST_ASIO_HAS_TIMERFD) +    }    }    // Interrupt the select loop.    void interrupt()    { -    interrupter_.interrupt(); +    epoll_event ev = { 0, { 0 } }; +    ev.events = EPOLLIN | EPOLLERR | EPOLLET; +    ev.data.ptr = &interrupter_; +    epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);    } +private:    // The hint to pass to epoll_create to size its data structures.    enum { epoll_size = 20000 }; @@ -606,117 +437,65 @@ private:      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 epoll_wait call. The timeout value is    // returned as a number of milliseconds. A return value of -1 indicates    // that epoll_wait 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; -    } +    return timer_queues_.wait_duration_msec(5 * 60 * 1000);    } -  // 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 epoll_reactor's mutex. -  void cancel_ops_unlocked(socket_type descriptor) +#if defined(BOOST_ASIO_HAS_TIMERFD) +  // Get the timeout value for the timer descriptor. The return value is the +  // flag argument to be used when calling timerfd_settime. +  int get_timeout(itimerspec& ts)    { -    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(); -  } +    ts.it_interval.tv_sec = 0; +    ts.it_interval.tv_nsec = 0; -  // 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 complete_operations_and_timers( -      boost::asio::detail::mutex::scoped_lock& lock) -  { -    timer_queues_for_cleanup_ = timer_queues_; -    lock.unlock(); -    read_op_queue_.complete_operations(); -    write_op_queue_.complete_operations(); -    except_op_queue_.complete_operations(); -    for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) -      timer_queues_for_cleanup_[i]->complete_timers(); +    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); +    ts.it_value.tv_sec = usec / 1000000; +    ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1; + +    return usec ? 0 : TFD_TIMER_ABSTIME;    } +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + +  // The io_service implementation used to post completions. +  io_service_impl& io_service_;    // Mutex to protect access to internal data. -  boost::asio::detail::mutex mutex_; +  mutex mutex_;    // The epoll file descriptor.    int epoll_fd_; -  // Whether the epoll_wait call is currently in progress -  bool wait_in_progress_; +  // The timer file descriptor. +  int timer_fd_;    // The interrupter is used to break a blocking epoll_wait call.    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. -  boost::asio::detail::thread* thread_; +  timer_queue_set timer_queues_;    // Whether the service has been shut down.    bool shutdown_; -  // Whether we need to call epoll_wait the next time the reactor is run. -  bool need_epoll_wait_; +  // Mutex to protect access to the registered descriptors. +  mutex registered_descriptors_mutex_; + +  // Keep track of all registered descriptors. This code relies on the fact that +  // the hash_map implementation pools deleted nodes, meaning that we can assume +  // our descriptor_state pointer remains valid even after the entry is removed. +  // Technically this is not true for C++98, as that standard says that spliced +  // elements in a list are invalidated. However, C++0x fixes this shortcoming +  // so we'll just assume that C++98 std::list implementations will do the right +  // thing anyway. +  typedef detail::hash_map<socket_type, descriptor_state> descriptor_map; +  descriptor_map registered_descriptors_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/epoll_reactor_fwd.hpp b/3rdParty/Boost/src/boost/asio/detail/epoll_reactor_fwd.hpp index 9659dd4..214cee5 100644 --- a/3rdParty/Boost/src/boost/asio/detail/epoll_reactor_fwd.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/epoll_reactor_fwd.hpp @@ -33,7 +33,6 @@ namespace boost {  namespace asio {  namespace detail { -template <bool Own_Thread>  class epoll_reactor;  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/event.hpp b/3rdParty/Boost/src/boost/asio/detail/event.hpp index 89f9896..e8d185f 100644 --- a/3rdParty/Boost/src/boost/asio/detail/event.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/event.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  # include <boost/asio/detail/null_event.hpp>  #elif defined(BOOST_WINDOWS)  # include <boost/asio/detail/win_event.hpp> @@ -35,7 +35,7 @@ namespace boost {  namespace asio {  namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  typedef null_event event;  #elif defined(BOOST_WINDOWS)  typedef win_event event; diff --git a/3rdParty/Boost/src/boost/asio/detail/fenced_block.hpp b/3rdParty/Boost/src/boost/asio/detail/fenced_block.hpp new file mode 100644 index 0000000..c80161f --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/fenced_block.hpp @@ -0,0 +1,72 @@ +// +// fenced_block.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/push_options.hpp> +#include <boost/config.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) +# include <boost/asio/detail/null_fenced_block.hpp> +#elif defined(__MACH__) && defined(__APPLE__) +# include <boost/asio/detail/macos_fenced_block.hpp> +#elif defined(__sun) +# include <boost/asio/detail/solaris_fenced_block.hpp> +#elif defined(__GNUC__) \ +  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ +  && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) +# include <boost/asio/detail/gcc_fenced_block.hpp> +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# include <boost/asio/detail/gcc_x86_fenced_block.hpp> +#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) +# include <boost/asio/detail/win_fenced_block.hpp> +#else +# include <boost/asio/detail/null_fenced_block.hpp> +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) +typedef null_fenced_block fenced_block; +#elif defined(__MACH__) && defined(__APPLE__) +typedef macos_fenced_block fenced_block; +#elif defined(__sun) +typedef solaris_fenced_block fenced_block; +#elif defined(__GNUC__) \ +  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ +  && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) +typedef gcc_fenced_block fenced_block; +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +typedef gcc_x86_fenced_block fenced_block; +#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) +typedef win_fenced_block fenced_block; +#else +typedef null_fenced_block fenced_block; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_FENCED_BLOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/gcc_fenced_block.hpp b/3rdParty/Boost/src/boost/asio/detail/gcc_fenced_block.hpp new file mode 100644 index 0000000..0c086a6 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/gcc_fenced_block.hpp @@ -0,0 +1,65 @@ +// +// gcc_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_GCC_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_GCC_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/push_options.hpp> +#include <boost/config.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#if defined(__GNUC__) \ +  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ +  && !defined(__INTEL_COMPILER) && !defined(__ICL) \ +  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) + +namespace boost { +namespace asio { +namespace detail { + +class gcc_fenced_block +  : private noncopyable +{ +public: +  // Constructor. +  gcc_fenced_block() +    : value_(0) +  { +    __sync_lock_test_and_set(&value_, 1); +  } + +  // Destructor. +  ~gcc_fenced_block() +  { +    __sync_lock_release(&value_); +  } + +private: +  int value_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(__GNUC__) +       // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) +       // && !defined(__INTEL_COMPILER) && !defined(__ICL) +       // && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_GCC_FENCED_BLOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/gcc_x86_fenced_block.hpp b/3rdParty/Boost/src/boost/asio/detail/gcc_x86_fenced_block.hpp new file mode 100644 index 0000000..fc23d66 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/gcc_x86_fenced_block.hpp @@ -0,0 +1,63 @@ +// +// gcc_x86_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/push_options.hpp> +#include <boost/config.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +namespace boost { +namespace asio { +namespace detail { + +class gcc_x86_fenced_block +  : private noncopyable +{ +public: +  // Constructor. +  gcc_x86_fenced_block() +  { +    barrier(); +  } + +  // Destructor. +  ~gcc_x86_fenced_block() +  { +    barrier(); +  } + +private: +  static int barrier() +  { +    int r = 0; +    __asm__ __volatile__ ("xchgl %%eax, %0" : "=m" (r) : : "memory", "cc"); +    return r; +  } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/handler_base_from_member.hpp b/3rdParty/Boost/src/boost/asio/detail/handler_base_from_member.hpp deleted file mode 100644 index 4e471e3..0000000 --- a/3rdParty/Boost/src/boost/asio/detail/handler_base_from_member.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// handler_base_from_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP -#define BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/push_options.hpp> - -#include <boost/asio/detail/handler_alloc_helpers.hpp> -#include <boost/asio/detail/handler_invoke_helpers.hpp> - -namespace boost { -namespace asio { -namespace detail { - -// Base class for classes that need a handler data member. Forwards the custom -// allocation and invocation hooks to the contained handler. -template <typename Handler> -class handler_base_from_member -{ -public: -  handler_base_from_member(Handler handler) -    : handler_(handler) -  { -  } - -//protected: -  Handler handler_; - -protected: -  // Protected destructor to prevent deletion through this type. -  ~handler_base_from_member() -  { -  } -}; - -template <typename Handler> -inline void* asio_handler_allocate(std::size_t size, -    handler_base_from_member<Handler>* this_handler) -{ -  return boost_asio_handler_alloc_helpers::allocate( -      size, this_handler->handler_); -} - -template <typename Handler> -inline void asio_handler_deallocate(void* pointer, std::size_t size, -    handler_base_from_member<Handler>* this_handler) -{ -  boost_asio_handler_alloc_helpers::deallocate( -      pointer, size, this_handler->handler_); -} - -template <typename Function, typename Handler> -inline void asio_handler_invoke(const Function& function, -    handler_base_from_member<Handler>* this_handler) -{ -  boost_asio_handler_invoke_helpers::invoke( -      function, this_handler->handler_); -} - -} // namespace detail -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/handler_queue.hpp b/3rdParty/Boost/src/boost/asio/detail/handler_queue.hpp deleted file mode 100644 index c1fb988..0000000 --- a/3rdParty/Boost/src/boost/asio/detail/handler_queue.hpp +++ /dev/null @@ -1,231 +0,0 @@ -// -// handler_queue.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP -#define BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/push_options.hpp> - -#include <boost/asio/detail/handler_alloc_helpers.hpp> -#include <boost/asio/detail/handler_invoke_helpers.hpp> -#include <boost/asio/detail/noncopyable.hpp> - -namespace boost { -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. -      boost_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); - -      // 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. -      Handler handler(h->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset(); -    } - -  private: -    Handler handler_; -  }; - -  // The front of the queue. -  handler* front_; - -  // The back of the queue. -  handler* back_; -}; - -} // namespace detail -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/hash_map.hpp b/3rdParty/Boost/src/boost/asio/detail/hash_map.hpp index c620da7..36c9a99 100644 --- a/3rdParty/Boost/src/boost/asio/detail/hash_map.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/hash_map.hpp @@ -21,7 +21,6 @@  #include <cassert>  #include <list>  #include <utility> -#include <vector>  #include <boost/functional/hash.hpp>  #include <boost/asio/detail/pop_options.hpp> @@ -62,9 +61,16 @@ public:    // Constructor.    hash_map() -    : size_(0) +    : size_(0), +      buckets_(0), +      num_buckets_(0)    { -    rehash(hash_size(0)); +  } + +  // Destructor. +  ~hash_map() +  { +    delete[] buckets_;    }    // Get an iterator for the beginning of the map. @@ -100,17 +106,20 @@ public:    // Find an entry in the map.    iterator find(const K& k)    { -    size_t bucket = calculate_hash_value(k) % buckets_.size(); -    iterator it = buckets_[bucket].first; -    if (it == values_.end()) -      return values_.end(); -    iterator end = buckets_[bucket].last; -    ++end; -    while (it != end) +    if (num_buckets_)      { -      if (it->first == k) -        return it; -      ++it; +      size_t bucket = calculate_hash_value(k) % num_buckets_; +      iterator it = buckets_[bucket].first; +      if (it == values_.end()) +        return values_.end(); +      iterator end = buckets_[bucket].last; +      ++end; +      while (it != end) +      { +        if (it->first == k) +          return it; +        ++it; +      }      }      return values_.end();    } @@ -118,17 +127,20 @@ public:    // Find an entry in the map.    const_iterator find(const K& k) const    { -    size_t bucket = calculate_hash_value(k) % buckets_.size(); -    const_iterator it = buckets_[bucket].first; -    if (it == values_.end()) -      return it; -    const_iterator end = buckets_[bucket].last; -    ++end; -    while (it != end) +    if (num_buckets_)      { -      if (it->first == k) +      size_t bucket = calculate_hash_value(k) % num_buckets_; +      const_iterator it = buckets_[bucket].first; +      if (it == values_.end())          return it; -      ++it; +      const_iterator end = buckets_[bucket].last; +      ++end; +      while (it != end) +      { +        if (it->first == k) +          return it; +        ++it; +      }      }      return values_.end();    } @@ -136,9 +148,9 @@ public:    // Insert a new entry into the map.    std::pair<iterator, bool> insert(const value_type& v)    { -    if (size_ + 1 >= buckets_.size()) +    if (size_ + 1 >= num_buckets_)        rehash(hash_size(size_ + 1)); -    size_t bucket = calculate_hash_value(v.first) % buckets_.size(); +    size_t bucket = calculate_hash_value(v.first) % num_buckets_;      iterator it = buckets_[bucket].first;      if (it == values_.end())      { @@ -165,7 +177,7 @@ public:    {      assert(it != values_.end()); -    size_t bucket = calculate_hash_value(it->first) % buckets_.size(); +    size_t bucket = calculate_hash_value(it->first) % num_buckets_;      bool is_first = (it == buckets_[bucket].first);      bool is_last = (it == buckets_[bucket].last);      if (is_first && is_last) @@ -179,6 +191,14 @@ public:      --size_;    } +  // Erase a key from the map. +  void erase(const K& k) +  { +    iterator it = find(k); +    if (it != values_.end()) +      erase(it); +  } +    // Remove all entries from the map.    void clear()    { @@ -187,8 +207,9 @@ public:      size_ = 0;      // Initialise all buckets to empty. -    for (size_t i = 0; i < buckets_.size(); ++i) -      buckets_[i].first = buckets_[i].last = values_.end(); +    iterator end = values_.end(); +    for (size_t i = 0; i < num_buckets_; ++i) +      buckets_[i].first = buckets_[i].last = end;    }  private: @@ -215,21 +236,24 @@ private:    // Re-initialise the hash from the values already contained in the list.    void rehash(std::size_t num_buckets)    { -    if (num_buckets == buckets_.size()) +    if (num_buckets == num_buckets_)        return; +    num_buckets_ = num_buckets;      iterator end = values_.end();      // Update number of buckets and initialise all buckets to empty. -    buckets_.resize(num_buckets); -    for (std::size_t i = 0; i < buckets_.size(); ++i) +    bucket_type* tmp = new bucket_type[num_buckets_]; +    delete[] buckets_; +    buckets_ = tmp; +    for (std::size_t i = 0; i < num_buckets_; ++i)        buckets_[i].first = buckets_[i].last = end;      // Put all values back into the hash.      iterator iter = values_.begin();      while (iter != end)      { -      std::size_t bucket = calculate_hash_value(iter->first) % buckets_.size(); +      std::size_t bucket = calculate_hash_value(iter->first) % num_buckets_;        if (buckets_[bucket].last == end)        {          buckets_[bucket].first = buckets_[bucket].last = iter++; @@ -282,14 +306,15 @@ private:    // The type for a bucket in the hash table.    struct bucket_type    { -    bucket_type() {} -    bucket_type(const bucket_type&) { /* noop */ }      iterator first;      iterator last;    };    // The buckets in the hash. -  std::vector<bucket_type> buckets_; +  bucket_type* buckets_; + +  // The number of buckets in the hash. +  std::size_t num_buckets_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/indirect_handler_queue.hpp b/3rdParty/Boost/src/boost/asio/detail/indirect_handler_queue.hpp deleted file mode 100644 index 72b1030..0000000 --- a/3rdParty/Boost/src/boost/asio/detail/indirect_handler_queue.hpp +++ /dev/null @@ -1,293 +0,0 @@ -// -// indirect_handler_queue.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP -#define BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/push_options.hpp> - -#include <boost/asio/detail/handler_alloc_helpers.hpp> -#include <boost/asio/detail/handler_invoke_helpers.hpp> -#include <boost/asio/detail/noncopyable.hpp> - -#if defined(_MSC_VER) && (_MSC_VER >= 1310) -extern "C" void _ReadWriteBarrier(); -# pragma intrinsic(_ReadWriteBarrier) -#endif // defined(_MSC_VER) && (_MSC_VER >= 1310) - -namespace boost { -namespace asio { -namespace detail { - -class indirect_handler_queue -  : private noncopyable -{ -public: -  class handler; - -  // Element for a node in the queue. -  class node -  { -  public: -    node() -      : version_(0), -        handler_(0), -        next_(0) -    { -    } - -  private: -    friend class indirect_handler_queue; -    unsigned long version_; -    handler* handler_; -    node* next_; -  }; - -  // 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) -      : node_(new node), -        invoke_func_(invoke_func), -        destroy_func_(destroy_func) -    { -    } - -    ~handler() -    { -      if (node_) -        delete node_; -    } - -  private: -    friend class indirect_handler_queue; -    node* node_; -    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. -  indirect_handler_queue() -    : front_(new node), -      back_(front_), -      next_version_(1) -  { -  } - -  // Destructor. -  ~indirect_handler_queue() -  { -    while (front_) -    { -      node* tmp = front_; -      front_ = front_->next_; -      delete tmp; -    } -  } - -  // 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(); -  } - -  // Determine whether the queue has something ready to pop. -  bool poppable() -  { -    return front_->next_ != 0; -  } - -  // The version number at the front of the queue. -  unsigned long front_version() -  { -    return front_->version_; -  } - -  // The version number at the back of the queue. -  unsigned long back_version() -  { -    return back_->version_; -  } - -  // Pop a handler from the front of the queue. -  handler* pop() -  { -    node* n = front_; -    node* new_front = n->next_; -    if (new_front) -    { -      handler* h = new_front->handler_; -      h->node_ = n; -      new_front->handler_ = 0; -      front_ = new_front; -      return h; -    } -    return 0; -  } - -  // Push a handler on to the back of the queue. -  void push(handler* h) -  { -    node* n = h->node_; -    h->node_ = 0; -    n->version_ = next_version_; -    next_version_ += 2; -    n->handler_ = h; -    n->next_ = 0; -    memory_barrier(); -    back_->next_ = n; -    back_ = n; -  } - -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. -      boost_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); - -      // 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. -      Handler handler(h->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset(); -    } - -  private: -    Handler handler_; -  }; - -  // Helper function to create a memory barrier. -  static void memory_barrier() -  { -#if defined(_GLIBCXX_WRITE_MEM_BARRIER) -    _GLIBCXX_WRITE_MEM_BARRIER; -#elif defined(_MSC_VER) && (_MSC_VER >= 1310) -    _ReadWriteBarrier(); -#else -# error memory barrier required -#endif -  } - -  // The front of the queue. -  node* front_; - -  // The back of the queue. -  node* back_; - -  // The next version counter to be assigned to a node. -  unsigned long next_version_; -}; - -} // namespace detail -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor.hpp b/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor.hpp index ea8e285..c1a6705 100644 --- a/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor.hpp @@ -24,28 +24,27 @@  #include <boost/asio/detail/push_options.hpp>  #include <cstddef> -#include <vector>  #include <sys/types.h>  #include <sys/event.h>  #include <sys/time.h>  #include <boost/config.hpp> -#include <boost/date_time/posix_time/posix_time_types.hpp>  #include <boost/throw_exception.hpp>  #include <boost/system/system_error.hpp>  #include <boost/asio/detail/pop_options.hpp>  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp> -#include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/hash_map.hpp>  #include <boost/asio/detail/mutex.hpp> -#include <boost/asio/detail/task_io_service.hpp> -#include <boost/asio/detail/thread.hpp> -#include <boost/asio/detail/reactor_op_queue.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/reactor_op.hpp>  #include <boost/asio/detail/select_interrupter.hpp>  #include <boost/asio/detail/service_base.hpp> -#include <boost/asio/detail/signal_blocker.hpp>  #include <boost/asio/detail/socket_types.hpp> -#include <boost/asio/detail/timer_queue.hpp> +#include <boost/asio/detail/timer_op.hpp> +#include <boost/asio/detail/timer_queue_base.hpp> +#include <boost/asio/detail/timer_queue_fwd.hpp> +#include <boost/asio/detail/timer_queue_set.hpp>  // Older versions of Mac OS X may not define EV_OOBAND.  #if !defined(EV_OOBAND) @@ -56,520 +55,368 @@ namespace boost {  namespace asio {  namespace detail { -template <bool Own_Thread>  class kqueue_reactor -  : public boost::asio::detail::service_base<kqueue_reactor<Own_Thread> > +  : public boost::asio::detail::service_base<kqueue_reactor>  {  public: -  // Per-descriptor data. -  struct per_descriptor_data +  enum op_types { read_op = 0, write_op = 1, +    connect_op = 1, except_op = 2, max_ops = 3 }; + +  // Per-descriptor queues. +  struct descriptor_state    { -    bool allow_speculative_read; -    bool allow_speculative_write; +    descriptor_state() {} +    descriptor_state(const descriptor_state&) {} +    void operator=(const descriptor_state&) {} + +    mutex mutex_; +    op_queue<reactor_op> op_queue_[max_ops]; +    bool shutdown_;    }; +  // Per-descriptor data. +  typedef descriptor_state* per_descriptor_data; +    // Constructor.    kqueue_reactor(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        kqueue_reactor<Own_Thread> >(io_service), +    : boost::asio::detail::service_base<kqueue_reactor>(io_service), +      io_service_(use_service<io_service_impl>(io_service)),        mutex_(),        kqueue_fd_(do_kqueue_create()), -      wait_in_progress_(false),        interrupter_(), -      read_op_queue_(), -      write_op_queue_(), -      except_op_queue_(), -      pending_cancellations_(), -      stop_thread_(false), -      thread_(0), -      shutdown_(false), -      need_kqueue_wait_(true) +      shutdown_(false)    { -    // Start the reactor's internal thread only if needed. -    if (Own_Thread) -    { -      boost::asio::detail::signal_blocker sb; -      thread_ = new boost::asio::detail::thread( -          bind_handler(&kqueue_reactor::call_run_thread, this)); -    } - -    // Add the interrupter's descriptor to the kqueue. -    struct kevent event; -    EV_SET(&event, interrupter_.read_descriptor(), -        EVFILT_READ, EV_ADD, 0, 0, 0); -    ::kevent(kqueue_fd_, &event, 1, 0, 0, 0); +    // The interrupter is put into a permanently readable state. Whenever we +    // want to interrupt the blocked kevent call we register a one-shot read +    // operation against the descriptor. +    interrupter_.interrupt();    }    // Destructor.    ~kqueue_reactor()    { -    shutdown_service();      close(kqueue_fd_);    }    // Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    mutex::scoped_lock lock(mutex_);      shutdown_ = true; -    stop_thread_ = true;      lock.unlock(); -    if (thread_) +    op_queue<operation> ops; + +    descriptor_map::iterator iter = registered_descriptors_.begin(); +    descriptor_map::iterator end = registered_descriptors_.end(); +    while (iter != end)      { -      interrupter_.interrupt(); -      thread_->join(); -      delete thread_; -      thread_ = 0; +      for (int i = 0; i < max_ops; ++i) +        ops.push(iter->second.op_queue_[i]); +      iter->second.shutdown_ = true; +      ++iter;      } -    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(); +    timer_queues_.get_all_timers(ops);    } -  // Initialise the task, but only if the reactor is not in its own thread. +  // Initialise the task.    void init_task()    { -    if (!Own_Thread) -    { -      typedef task_io_service<kqueue_reactor<Own_Thread> > task_io_service_type; -      use_service<task_io_service_type>(this->get_io_service()).init_task(); -    } +    io_service_.init_task();    }    // Register a socket with the reactor. Returns 0 on success, system error    // code on failure. -  int register_descriptor(socket_type, per_descriptor_data& descriptor_data) +  int register_descriptor(socket_type descriptor, +      per_descriptor_data& descriptor_data)    { -    descriptor_data.allow_speculative_read = true; -    descriptor_data.allow_speculative_write = true; +    mutex::scoped_lock lock(registered_descriptors_mutex_); + +    descriptor_map::iterator new_entry = registered_descriptors_.insert( +          std::make_pair(descriptor, descriptor_state())).first; +    descriptor_data = &new_entry->second; + +    descriptor_data->shutdown_ = false;      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, -      per_descriptor_data& descriptor_data, Handler handler, -      bool allow_speculative_read = true) +  // Start a new operation. The reactor operation will be performed when the +  // given descriptor is flagged as ready, or an error has occurred. +  void start_op(int op_type, socket_type descriptor, +      per_descriptor_data& descriptor_data, +      reactor_op* op, bool allow_speculative)    { -    if (allow_speculative_read && descriptor_data.allow_speculative_read) -    { -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) -      { -        handler.complete(ec, bytes_transferred); -        return; -      } - -      // We only get one shot at a speculative read in this function. -      allow_speculative_read = false; -    } - -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    if (shutdown_) +    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); +    if (descriptor_data->shutdown_)        return; -    if (!allow_speculative_read) -      need_kqueue_wait_ = true; -    else if (!read_op_queue_.has_operation(descriptor)) +    bool first = descriptor_data->op_queue_[op_type].empty(); +    if (first)      { -      // Speculative reads are ok as there are no queued read operations. -      descriptor_data.allow_speculative_read = true; - -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) +      if (allow_speculative)        { -        handler.complete(ec, bytes_transferred); -        return; +        if (op_type != read_op || descriptor_data->op_queue_[except_op].empty()) +        { +          if (op->perform()) +          { +            descriptor_lock.unlock(); +            io_service_.post_immediate_completion(op); +            return; +          } +        }        }      } -    // Speculative reads are not ok as there will be queued read operations. -    descriptor_data.allow_speculative_read = false; +    descriptor_data->op_queue_[op_type].push(op); +    io_service_.work_started(); -    if (read_op_queue_.enqueue_operation(descriptor, handler)) +    if (first)      {        struct kevent event; -      EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); +      switch (op_type) +      { +      case read_op: +        EV_SET(&event, descriptor, EVFILT_READ, +            EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); +        break; +      case write_op: +        EV_SET(&event, descriptor, EVFILT_WRITE, +            EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); +        break; +      case except_op: +        if (!descriptor_data->op_queue_[read_op].empty()) +          return; // Already registered for read events. +        EV_SET(&event, descriptor, EVFILT_READ, +            EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data); +        break; +      } +        if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)        { -        boost::system::error_code ec(errno, +        op->ec_ = boost::system::error_code(errno,              boost::asio::error::get_system_category()); -        read_op_queue_.perform_all_operations(descriptor, ec); +        descriptor_data->op_queue_[op_type].pop(); +        io_service_.post_deferred_completion(op);        }      }    } -  // 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, -      per_descriptor_data& descriptor_data, Handler handler, -      bool allow_speculative_write = true) +  // 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, per_descriptor_data& descriptor_data)    { -    if (allow_speculative_write && descriptor_data.allow_speculative_write) -    { -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) -      { -        handler.complete(ec, bytes_transferred); -        return; -      } - -      // We only get one shot at a speculative write in this function. -      allow_speculative_write = false; -    } +    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    if (shutdown_) -      return; - -    if (!allow_speculative_write) -      need_kqueue_wait_ = true; -    else if (!write_op_queue_.has_operation(descriptor)) +    op_queue<operation> ops; +    for (int i = 0; i < max_ops; ++i)      { -      // Speculative writes are ok as there are no queued write operations. -      descriptor_data.allow_speculative_write = true; - -      boost::system::error_code ec; -      std::size_t bytes_transferred = 0; -      if (handler.perform(ec, bytes_transferred)) +      while (reactor_op* op = descriptor_data->op_queue_[i].front())        { -        handler.complete(ec, bytes_transferred); -        return; +        op->ec_ = boost::asio::error::operation_aborted; +        descriptor_data->op_queue_[i].pop(); +        ops.push(op);        }      } -    // Speculative writes are not ok as there will be queued write operations. -    descriptor_data.allow_speculative_write = false; +    descriptor_lock.unlock(); -    if (write_op_queue_.enqueue_operation(descriptor, handler)) -    { -      struct kevent event; -      EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); -      if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) -      { -        boost::system::error_code ec(errno, -            boost::asio::error::get_system_category()); -        write_op_queue_.perform_all_operations(descriptor, ec); -      } -    } +    io_service_.post_deferred_completions(ops);    } -  // 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, -      per_descriptor_data&, Handler handler) +  // Cancel any operations that are running against the descriptor and remove +  // its registration from the reactor. +  void close_descriptor(socket_type descriptor, +      per_descriptor_data& descriptor_data)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); +    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); -    if (shutdown_) -      return; +    // Remove the descriptor from the set of known descriptors. The descriptor +    // will be automatically removed from the kqueue set when it is closed. +    descriptor_data->shutdown_ = true; -    if (except_op_queue_.enqueue_operation(descriptor, handler)) +    op_queue<operation> ops; +    for (int i = 0; i < max_ops; ++i)      { -      struct kevent event; -      if (read_op_queue_.has_operation(descriptor)) -        EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); -      else -        EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); -      if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) +      while (reactor_op* op = descriptor_data->op_queue_[i].front())        { -        boost::system::error_code ec(errno, -            boost::asio::error::get_system_category()); -        except_op_queue_.perform_all_operations(descriptor, ec); +        op->ec_ = boost::asio::error::operation_aborted; +        descriptor_data->op_queue_[i].pop(); +        ops.push(op);        }      } -  } - -  // 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_connect_op(socket_type descriptor, -      per_descriptor_data& descriptor_data, Handler handler) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    if (shutdown_) -      return; -    // Speculative writes are not ok as there will be queued write operations. -    descriptor_data.allow_speculative_write = false; +    descriptor_lock.unlock(); -    if (write_op_queue_.enqueue_operation(descriptor, handler)) -    { -      struct kevent event; -      EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); -      if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) -      { -        boost::system::error_code ec(errno, -            boost::asio::error::get_system_category()); -        write_op_queue_.perform_all_operations(descriptor, ec); -      } -    } -  } +    registered_descriptors_.erase(descriptor); -  // 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, per_descriptor_data&) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    cancel_ops_unlocked(descriptor); -  } +    descriptors_lock.unlock(); -  // Cancel any operations that are running against the descriptor and remove -  // its registration from the reactor. -  void close_descriptor(socket_type descriptor, per_descriptor_data&) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    // Remove the descriptor from kqueue. -    struct kevent event[2]; -    EV_SET(&event[0], descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); -    EV_SET(&event[1], descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); -    ::kevent(kqueue_fd_, event, 2, 0, 0, 0); -     -    // Cancel any outstanding operations associated with the descriptor. -    cancel_ops_unlocked(descriptor); +    io_service_.post_deferred_completions(ops);    }    // Add a new timer queue to the reactor.    template <typename Time_Traits>    void add_timer_queue(timer_queue<Time_Traits>& timer_queue)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    timer_queues_.push_back(&timer_queue); +    mutex::scoped_lock lock(mutex_); +    timer_queues_.insert(&timer_queue);    }    // Remove a timer queue from the reactor.    template <typename Time_Traits>    void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)    { -    boost::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; -      } -    } +    mutex::scoped_lock lock(mutex_); +    timer_queues_.erase(&timer_queue);    } -  // 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> +  // Schedule a new operation in the given timer queue to expire at the +  // specified absolute time. +  template <typename Time_Traits>    void schedule_timer(timer_queue<Time_Traits>& timer_queue, -      const typename Time_Traits::time_type& time, Handler handler, void* token) +      const typename Time_Traits::time_type& time, timer_op* op, void* token)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    mutex::scoped_lock lock(mutex_);      if (!shutdown_) -      if (timer_queue.enqueue_timer(time, handler, token)) -        interrupter_.interrupt(); +    { +      bool earliest = timer_queue.enqueue_timer(time, op, token); +      io_service_.work_started(); +      if (earliest) +        interrupt(); +    }    } -  // Cancel the timer associated with the given token. Returns the number of -  // handlers that have been posted or dispatched. +  // Cancel the timer operations associated with the given token. Returns the +  // number of operations that have been posted or dispatched.    template <typename Time_Traits>    std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    std::size_t n = timer_queue.cancel_timer(token); -    if (n > 0) -      interrupter_.interrupt(); +    mutex::scoped_lock lock(mutex_); +    op_queue<operation> ops; +    std::size_t n = timer_queue.cancel_timer(token, ops); +    lock.unlock(); +    io_service_.post_deferred_completions(ops);      return n;    } -private: -  friend class task_io_service<kqueue_reactor<Own_Thread> >; -    // Run the kqueue loop. -  void run(bool block) +  void run(bool block, op_queue<operation>& ops)    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    // Dispatch any operation cancellations that were made while the select -    // loop was not running. -    read_op_queue_.perform_cancellations(); -    write_op_queue_.perform_cancellations(); -    except_op_queue_.perform_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_) -    { -      complete_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()) -    { -      complete_operations_and_timers(lock); -      return; -    } +    mutex::scoped_lock lock(mutex_);      // Determine how long to block while waiting for events.      timespec timeout_buf = { 0, 0 };      timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf; -    wait_in_progress_ = true;      lock.unlock();      // Block on the kqueue descriptor.      struct kevent events[128]; -    int num_events = (block || need_kqueue_wait_) -      ? kevent(kqueue_fd_, 0, 0, events, 128, timeout) -      : 0; - -    lock.lock(); -    wait_in_progress_ = false; +    int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);      // Dispatch the waiting events.      for (int i = 0; i < num_events; ++i)      {        int descriptor = events[i].ident; -      if (descriptor == interrupter_.read_descriptor()) +      void* ptr = events[i].udata; +      if (ptr == &interrupter_)        { -        interrupter_.reset(); +        // No need to reset the interrupter since we're leaving the descriptor +        // in a ready-to-read state and relying on one-shot notifications.        } -      else if (events[i].filter == EVFILT_READ) +      else        { -        // Dispatch operations associated with the descriptor. -        bool more_reads = false; -        bool more_except = false; -        if (events[i].flags & EV_ERROR) +        descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr); +        mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + +        // Exception operations must be processed first to ensure that any +        // out-of-band data is read before normal data. +        static const int filter[max_ops] = +          { EVFILT_READ, EVFILT_WRITE, EVFILT_READ }; +        for (int j = max_ops - 1; j >= 0; --j)          { -          boost::system::error_code error( -              events[i].data, boost::asio::error::get_system_category()); -          except_op_queue_.perform_all_operations(descriptor, error); -          read_op_queue_.perform_all_operations(descriptor, error); -        } -        else if (events[i].flags & EV_OOBAND) -        { -          boost::system::error_code error; -          more_except = except_op_queue_.perform_operation(descriptor, error); -          if (events[i].data > 0) -            more_reads = read_op_queue_.perform_operation(descriptor, error); -          else -            more_reads = read_op_queue_.has_operation(descriptor); -        } -        else -        { -          boost::system::error_code error; -          more_reads = read_op_queue_.perform_operation(descriptor, error); -          more_except = except_op_queue_.has_operation(descriptor); +          if (events[i].filter == filter[j]) +          { +            if (j != except_op || events[i].flags & EV_OOBAND) +            { +              while (reactor_op* op = descriptor_data->op_queue_[j].front()) +              { +                if (events[i].flags & EV_ERROR) +                { +                  op->ec_ = boost::system::error_code(events[i].data, +                      boost::asio::error::get_system_category()); +                  descriptor_data->op_queue_[j].pop(); +                  ops.push(op); +                } +                if (op->perform()) +                { +                  descriptor_data->op_queue_[j].pop(); +                  ops.push(op); +                } +                else +                  break; +              } +            } +          }          } -        // Update the descriptor in the kqueue. +        // Renew registration for event notifications.          struct kevent event; -        if (more_reads) -          EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); -        else if (more_except) -          EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); -        else -          EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); -        if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) -        { -          boost::system::error_code error(errno, -              boost::asio::error::get_system_category()); -          except_op_queue_.perform_all_operations(descriptor, error); -          read_op_queue_.perform_all_operations(descriptor, error); -        } -      } -      else if (events[i].filter == EVFILT_WRITE) -      { -        // Dispatch operations associated with the descriptor. -        bool more_writes = false; -        if (events[i].flags & EV_ERROR) -        { -          boost::system::error_code error( -              events[i].data, boost::asio::error::get_system_category()); -          write_op_queue_.perform_all_operations(descriptor, error); -        } -        else +        switch (events[i].filter)          { -          boost::system::error_code error; -          more_writes = write_op_queue_.perform_operation(descriptor, error); +        case EVFILT_READ: +          if (!descriptor_data->op_queue_[read_op].empty()) +            EV_SET(&event, descriptor, EVFILT_READ, +                EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); +          else if (!descriptor_data->op_queue_[except_op].empty()) +            EV_SET(&event, descriptor, EVFILT_READ, +                EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data); +          else +            continue; +        case EVFILT_WRITE: +          if (!descriptor_data->op_queue_[write_op].empty()) +            EV_SET(&event, descriptor, EVFILT_WRITE, +                EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); +          else +            continue; +        default: +          break;          } - -        // Update the descriptor in the kqueue. -        struct kevent event; -        if (more_writes) -          EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); -        else -          EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0);          if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)          {            boost::system::error_code error(errno,                boost::asio::error::get_system_category()); -          write_op_queue_.perform_all_operations(descriptor, error); +          for (int j = 0; j < max_ops; ++j) +          { +            while (reactor_op* op = descriptor_data->op_queue_[j].front()) +            { +              op->ec_ = error; +              descriptor_data->op_queue_[j].pop(); +              ops.push(op); +            } +          }          }        }      } -    read_op_queue_.perform_cancellations(); -    write_op_queue_.perform_cancellations(); -    except_op_queue_.perform_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 (std::size_t i = 0; i < pending_cancellations_.size(); ++i) -      cancel_ops_unlocked(pending_cancellations_[i]); -    pending_cancellations_.clear(); - -    // Determine whether kqueue needs to be called next time the reactor is run. -    need_kqueue_wait_ = !read_op_queue_.empty() -      || !write_op_queue_.empty() || !except_op_queue_.empty(); - -    complete_operations_and_timers(lock); -  } - -  // Run the select loop in the thread. -  void run_thread() -  { -    boost::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(kqueue_reactor* reactor) -  { -    reactor->run_thread(); +    lock.lock(); +    timer_queues_.get_ready_timers(ops);    } -  // Interrupt the select loop. +  // Interrupt the kqueue loop.    void interrupt()    { -    interrupter_.interrupt(); +    struct kevent event; +    EV_SET(&event, interrupter_.read_descriptor(), +        EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_); +    ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);    } +private:    // Create the kqueue file descriptor. Throws an exception if the descriptor    // cannot be created.    static int do_kqueue_create() @@ -586,118 +433,47 @@ private:      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 kevent call.    timespec* get_timeout(timespec& ts)    { -    if (all_timer_queues_are_empty()) -      return 0; -      // 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()) -    { -      ts.tv_sec = minimum_wait_duration.total_seconds(); -      ts.tv_nsec = minimum_wait_duration.total_nanoseconds() % 1000000000; -    } -    else -    { -      ts.tv_sec = 0; -      ts.tv_nsec = 0; -    } - +    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); +    ts.tv_sec = usec / 1000000; +    ts.tv_nsec = (usec % 1000000) * 1000;      return &ts;    } -  // 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 kqueue_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 complete_operations_and_timers( -      boost::asio::detail::mutex::scoped_lock& lock) -  { -    timer_queues_for_cleanup_ = timer_queues_; -    lock.unlock(); -    read_op_queue_.complete_operations(); -    write_op_queue_.complete_operations(); -    except_op_queue_.complete_operations(); -    for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) -      timer_queues_for_cleanup_[i]->complete_timers(); -  } +  // The io_service implementation used to post completions. +  io_service_impl& io_service_;    // Mutex to protect access to internal data. -  boost::asio::detail::mutex mutex_; +  mutex mutex_;    // The kqueue file descriptor.    int kqueue_fd_; -  // Whether the kqueue wait call is currently in progress -  bool wait_in_progress_; -    // The interrupter is used to break a blocking kevent call.    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. -  boost::asio::detail::thread* thread_; +  timer_queue_set timer_queues_;    // Whether the service has been shut down.    bool shutdown_; -  // Whether we need to call kqueue the next time the reactor is run. -  bool need_kqueue_wait_; +  // Mutex to protect access to the registered descriptors. +  mutex registered_descriptors_mutex_; + +  // Keep track of all registered descriptors. This code relies on the fact that +  // the hash_map implementation pools deleted nodes, meaning that we can assume +  // our descriptor_state pointer remains valid even after the entry is removed. +  // Technically this is not true for C++98, as that standard says that spliced +  // elements in a list are invalidated. However, C++0x fixes this shortcoming +  // so we'll just assume that C++98 std::list implementations will do the right +  // thing anyway. +  typedef detail::hash_map<socket_type, descriptor_state> descriptor_map; +  descriptor_map registered_descriptors_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor_fwd.hpp b/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor_fwd.hpp index b2751bf..0471c39 100644 --- a/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor_fwd.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/kqueue_reactor_fwd.hpp @@ -30,7 +30,6 @@ namespace boost {  namespace asio {  namespace detail { -template <bool Own_Thread>  class kqueue_reactor;  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/macos_fenced_block.hpp b/3rdParty/Boost/src/boost/asio/detail/macos_fenced_block.hpp new file mode 100644 index 0000000..496d7f0 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/macos_fenced_block.hpp @@ -0,0 +1,59 @@ +// +// macos_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/push_options.hpp> +#include <boost/config.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#if defined(__MACH__) && defined(__APPLE__) + +#include <boost/asio/detail/push_options.hpp> +#include <libkern/OSAtomic.h> +#include <boost/asio/detail/pop_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class macos_fenced_block +  : private noncopyable +{ +public: +  // Constructor. +  macos_fenced_block() +  { +    OSMemoryBarrier(); +  } + +  // Destructor. +  ~macos_fenced_block() +  { +    OSMemoryBarrier(); +  } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(__MACH__) && defined(__APPLE__) + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/mutex.hpp b/3rdParty/Boost/src/boost/asio/detail/mutex.hpp index fc7ed83..e804ec2 100644 --- a/3rdParty/Boost/src/boost/asio/detail/mutex.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/mutex.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  # include <boost/asio/detail/null_mutex.hpp>  #elif defined(BOOST_WINDOWS)  # include <boost/asio/detail/win_mutex.hpp> @@ -35,7 +35,7 @@ namespace boost {  namespace asio {  namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  typedef null_mutex mutex;  #elif defined(BOOST_WINDOWS)  typedef win_mutex mutex; diff --git a/3rdParty/Boost/src/boost/asio/detail/null_buffers_op.hpp b/3rdParty/Boost/src/boost/asio/detail/null_buffers_op.hpp new file mode 100644 index 0000000..02160af --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/null_buffers_op.hpp @@ -0,0 +1,79 @@ +// +// null_buffers_op.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_BUFFERS_OP_HPP +#define BOOST_ASIO_DETAIL_NULL_BUFFERS_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/fenced_block.hpp> +#include <boost/asio/detail/handler_alloc_helpers.hpp> +#include <boost/asio/detail/handler_invoke_helpers.hpp> +#include <boost/asio/detail/reactor_op.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Handler> +class null_buffers_op : public reactor_op +{ +public: +  null_buffers_op(Handler handler) +    : reactor_op(&null_buffers_op::do_perform, &null_buffers_op::do_complete), +      handler_(handler) +  { +  } + +  static bool do_perform(reactor_op*) +  { +    return true; +  } + +  static void do_complete(io_service_impl* owner, operation* base, +      boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) +  { +    // Take ownership of the handler object. +    null_buffers_op* o(static_cast<null_buffers_op*>(base)); +    typedef handler_alloc_traits<Handler, null_buffers_op> alloc_traits; +    handler_ptr<alloc_traits> ptr(o->handler_, o); + +    // Make the upcall if required. +    if (owner) +    { +      // 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, std::size_t> +        handler(o->handler_, o->ec_, o->bytes_transferred_); +      ptr.reset(); +      boost::asio::detail::fenced_block b; +      boost_asio_handler_invoke_helpers::invoke(handler, handler); +    } +  } + +private: +  Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_NULL_BUFFERS_OP_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/null_event.hpp b/3rdParty/Boost/src/boost/asio/detail/null_event.hpp index 184f753..2dc0bf6 100644 --- a/3rdParty/Boost/src/boost/asio/detail/null_event.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/null_event.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/noncopyable.hpp> @@ -49,6 +49,12 @@ public:    {    } +  // Signal the event and unlock the mutex. +  template <typename Lock> +  void signal_and_unlock(Lock&) +  { +  } +    // Reset the event.    template <typename Lock>    void clear(Lock&) @@ -66,7 +72,7 @@ public:  } // namespace asio  } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/pop_options.hpp> diff --git a/3rdParty/Boost/src/boost/asio/detail/null_fenced_block.hpp b/3rdParty/Boost/src/boost/asio/detail/null_fenced_block.hpp new file mode 100644 index 0000000..ea8e0fc --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/null_fenced_block.hpp @@ -0,0 +1,45 @@ +// +// null_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_NULL_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class null_fenced_block +  : private noncopyable +{ +public: +  // Constructor. +  null_fenced_block() +  { +  } + +  // Destructor. +  ~null_fenced_block() +  { +  } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_NULL_FENCED_BLOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/null_mutex.hpp b/3rdParty/Boost/src/boost/asio/detail/null_mutex.hpp index bdf5617..edc1358 100644 --- a/3rdParty/Boost/src/boost/asio/detail/null_mutex.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/null_mutex.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/noncopyable.hpp>  #include <boost/asio/detail/scoped_lock.hpp> @@ -61,7 +61,7 @@ public:  } // namespace asio  } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/pop_options.hpp> diff --git a/3rdParty/Boost/src/boost/asio/detail/null_signal_blocker.hpp b/3rdParty/Boost/src/boost/asio/detail/null_signal_blocker.hpp index 7fe5c10..65b55e9 100644 --- a/3rdParty/Boost/src/boost/asio/detail/null_signal_blocker.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/null_signal_blocker.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/noncopyable.hpp> @@ -58,7 +58,7 @@ public:  } // namespace asio  } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/pop_options.hpp> diff --git a/3rdParty/Boost/src/boost/asio/detail/null_thread.hpp b/3rdParty/Boost/src/boost/asio/detail/null_thread.hpp index 0a508f3..ba16311 100644 --- a/3rdParty/Boost/src/boost/asio/detail/null_thread.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/null_thread.hpp @@ -22,7 +22,7 @@  #include <boost/system/system_error.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/push_options.hpp>  #include <boost/throw_exception.hpp> @@ -63,7 +63,7 @@ public:  } // namespace asio  } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/pop_options.hpp> diff --git a/3rdParty/Boost/src/boost/asio/detail/null_tss_ptr.hpp b/3rdParty/Boost/src/boost/asio/detail/null_tss_ptr.hpp index 7c35b15..bd83e7e 100644 --- a/3rdParty/Boost/src/boost/asio/detail/null_tss_ptr.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/null_tss_ptr.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/noncopyable.hpp> @@ -65,7 +65,7 @@ private:  } // namespace asio  } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  #include <boost/asio/detail/pop_options.hpp> diff --git a/3rdParty/Boost/src/boost/asio/detail/op_queue.hpp b/3rdParty/Boost/src/boost/asio/detail/op_queue.hpp new file mode 100644 index 0000000..ddf3e18 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/op_queue.hpp @@ -0,0 +1,158 @@ +// +// op_queue.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_OP_QUEUE_HPP +#define BOOST_ASIO_DETAIL_OP_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/noncopyable.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Operation> +class op_queue; + +class op_queue_access +{ +public: +  template <typename Operation> +  static Operation* next(Operation* o) +  { +    return static_cast<Operation*>(o->next_); +  } + +  template <typename Operation1, typename Operation2> +  static void next(Operation1*& o1, Operation2* o2) +  { +    o1->next_ = o2; +  } + +  template <typename Operation> +  static void destroy(Operation* o) +  { +    o->destroy(); +  } + +  template <typename Operation> +  static Operation*& front(op_queue<Operation>& q) +  { +    return q.front_; +  } + +  template <typename Operation> +  static Operation*& back(op_queue<Operation>& q) +  { +    return q.back_; +  } +}; + +template <typename Operation> +class op_queue +  : private noncopyable +{ +public: +  // Constructor. +  op_queue() +    : front_(0), +      back_(0) +  { +  } + +  // Destructor destroys all operations. +  ~op_queue() +  { +    while (Operation* op = front_) +    { +      pop(); +      op_queue_access::destroy(op); +    } +  } + +  // Get the operation at the front of the queue. +  Operation* front() +  { +    return front_; +  } + +  // Pop an operation from the front of the queue. +  void pop() +  { +    if (front_) +    { +      Operation* tmp = front_; +      front_ = op_queue_access::next(front_); +      if (front_ == 0) +        back_ = 0; +      op_queue_access::next(tmp, static_cast<Operation*>(0)); +    } +  } + +  // Push an operation on to the back of the queue. +  void push(Operation* h) +  { +    op_queue_access::next(h, static_cast<Operation*>(0)); +    if (back_) +    { +      op_queue_access::next(back_, h); +      back_ = h; +    } +    else +    { +      front_ = back_ = h; +    } +  } + +  // Push all operations from another queue on to the back of the queue. The +  // source queue may contain operations of a derived type. +  template <typename OtherOperation> +  void push(op_queue<OtherOperation>& q) +  { +    if (Operation* other_front = op_queue_access::front(q)) +    { +      if (back_) +        op_queue_access::next(back_, other_front); +      else +        front_ = other_front; +      back_ = op_queue_access::back(q); +      op_queue_access::front(q) = 0; +      op_queue_access::back(q) = 0; +    } +  } + +  // Whether the queue is empty. +  bool empty() const +  { +    return front_ == 0; +  } + +private: +  friend class op_queue_access; + +  // The front of the queue. +  Operation* front_; + +  // The back of the queue. +  Operation* back_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_OP_QUEUE_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/operation.hpp b/3rdParty/Boost/src/boost/asio/detail/operation.hpp new file mode 100644 index 0000000..579b6b5 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/operation.hpp @@ -0,0 +1,45 @@ +// +// operation.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_OPERATION_HPP +#define BOOST_ASIO_DETAIL_OPERATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/win_iocp_io_service_fwd.hpp> + +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_operation.hpp> +#else +# include <boost/asio/detail/reactor_fwd.hpp> +# include <boost/asio/detail/task_io_service_operation.hpp> +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_HAS_IOCP) +typedef win_iocp_operation operation; +#else +typedef task_io_service_operation<reactor> operation; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_OPERATION_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/posix_event.hpp b/3rdParty/Boost/src/boost/asio/detail/posix_event.hpp index 20c0fe3..b2938cf 100644 --- a/3rdParty/Boost/src/boost/asio/detail/posix_event.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/posix_event.hpp @@ -72,6 +72,16 @@ public:      ::pthread_cond_signal(&cond_); // Ignore EINVAL.    } +  // Signal the event and unlock the mutex. +  template <typename Lock> +  void signal_and_unlock(Lock& lock) +  { +    BOOST_ASSERT(lock.locked()); +    signalled_ = true; +    lock.unlock(); +    ::pthread_cond_signal(&cond_); // Ignore EINVAL. +  } +    // Reset the event.    template <typename Lock>    void clear(Lock& lock) diff --git a/3rdParty/Boost/src/boost/asio/detail/posix_mutex.hpp b/3rdParty/Boost/src/boost/asio/detail/posix_mutex.hpp index e7209c1..6d9a44f 100644 --- a/3rdParty/Boost/src/boost/asio/detail/posix_mutex.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/posix_mutex.hpp @@ -62,35 +62,19 @@ public:    // Destructor.    ~posix_mutex()    { -    ::pthread_mutex_destroy(&mutex_); +    ::pthread_mutex_destroy(&mutex_); // Ignore EBUSY.    }    // Lock the mutex.    void lock()    { -    int error = ::pthread_mutex_lock(&mutex_); -    if (error != 0) -    { -      boost::system::system_error e( -          boost::system::error_code(error, -            boost::asio::error::get_system_category()), -          "mutex"); -      boost::throw_exception(e); -    } +    (void)::pthread_mutex_lock(&mutex_); // Ignore EINVAL.    }    // Unlock the mutex.    void unlock()    { -    int error = ::pthread_mutex_unlock(&mutex_); -    if (error != 0) -    { -      boost::system::system_error e( -          boost::system::error_code(error, -            boost::asio::error::get_system_category()), -          "mutex"); -      boost::throw_exception(e); -    } +    (void)::pthread_mutex_unlock(&mutex_); // Ignore EINVAL.    }  private: diff --git a/3rdParty/Boost/src/boost/asio/detail/reactive_descriptor_service.hpp b/3rdParty/Boost/src/boost/asio/detail/reactive_descriptor_service.hpp index 61f676b..536b96a 100644 --- a/3rdParty/Boost/src/boost/asio/detail/reactive_descriptor_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/reactive_descriptor_service.hpp @@ -21,10 +21,13 @@  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp>  #include <boost/asio/detail/bind_handler.hpp> -#include <boost/asio/detail/handler_base_from_member.hpp> -#include <boost/asio/detail/noncopyable.hpp> -#include <boost/asio/detail/service_base.hpp> +#include <boost/asio/detail/buffer_sequence_adapter.hpp>  #include <boost/asio/detail/descriptor_ops.hpp> +#include <boost/asio/detail/fenced_block.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/null_buffers_op.hpp> +#include <boost/asio/detail/reactor.hpp> +#include <boost/asio/detail/reactor_op.hpp>  #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) @@ -32,10 +35,7 @@ namespace boost {  namespace asio {  namespace detail { -template <typename Reactor>  class reactive_descriptor_service -  : public boost::asio::detail::service_base< -      reactive_descriptor_service<Reactor> >  {  public:    // The native type of a descriptor. @@ -55,22 +55,28 @@ public:    private:      // Only this service will have access to the internal values. -    friend class reactive_descriptor_service<Reactor>; +    friend class reactive_descriptor_service;      // The native descriptor representation.      int descriptor_;      enum      { -      user_set_non_blocking = 1, // The user wants a non-blocking descriptor. -      internal_non_blocking = 2  // The descriptor has been set non-blocking. +      // The user wants a non-blocking descriptor. +      user_set_non_blocking = 1, + +      // The descriptor has been set non-blocking. +      internal_non_blocking = 2, + +      // Helper "flag" used to determine whether the descriptor is non-blocking. +      non_blocking = user_set_non_blocking | internal_non_blocking      };      // Flags indicating the current state of the descriptor.      unsigned char flags_;      // Per-descriptor data used by the reactor. -    typename Reactor::per_descriptor_data reactor_data_; +    reactor::per_descriptor_data reactor_data_;    };    // The maximum number of buffers to support in a single operation. @@ -78,9 +84,8 @@ public:    // Constructor.    reactive_descriptor_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        reactive_descriptor_service<Reactor> >(io_service), -      reactor_(boost::asio::use_service<Reactor>(io_service)) +    : io_service_impl_(boost::asio::use_service<io_service_impl>(io_service)), +      reactor_(boost::asio::use_service<reactor>(io_service))    {      reactor_.init_task();    } @@ -209,19 +214,31 @@ public:        return ec;      } -    if (command.name() == static_cast<int>(FIONBIO)) +    descriptor_ops::ioctl(impl.descriptor_, command.name(), +        static_cast<ioctl_arg_type*>(command.data()), ec); + +    // When updating the non-blocking mode we always perform the ioctl syscall, +    // even if the flags would otherwise indicate that the descriptor is +    // already in the correct state. This ensures that the underlying +    // descriptor is put into the state that has been requested by the user. If +    // the ioctl syscall was successful then we need to update the flags to +    // match. +    if (!ec && command.name() == static_cast<int>(FIONBIO))      { -      if (command.get()) +      if (*static_cast<ioctl_arg_type*>(command.data())) +      {          impl.flags_ |= implementation_type::user_set_non_blocking; +      }        else -        impl.flags_ &= ~implementation_type::user_set_non_blocking; -      ec = boost::system::error_code(); -    } -    else -    { -      descriptor_ops::ioctl(impl.descriptor_, command.name(), -          static_cast<ioctl_arg_type*>(command.data()), ec); +      { +        // Clearing the non-blocking mode always overrides any internally-set +        // non-blocking flag. Any subsequent asynchronous operations will need +        // to re-enable non-blocking I/O. +        impl.flags_ &= ~(implementation_type::user_set_non_blocking +            | implementation_type::internal_non_blocking); +      }      } +      return ec;    } @@ -236,47 +253,22 @@ public:        return 0;      } -    // Copy buffers into array. -    descriptor_ops::buf bufs[max_buffers]; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    size_t i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::const_buffer buffer(*iter); -      descriptor_ops::init_buf(bufs[i], -          boost::asio::buffer_cast<const void*>(buffer), -          boost::asio::buffer_size(buffer)); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } +    buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence> bufs(buffers);      // A request to read_some 0 bytes on a stream is a no-op. -    if (total_buffer_size == 0) +    if (bufs.all_empty())      {        ec = boost::system::error_code();        return 0;      } -    // Make descriptor non-blocking if user wants non-blocking. -    if (impl.flags_ & implementation_type::user_set_non_blocking) -    { -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) -      { -        ioctl_arg_type non_blocking = 1; -        if (descriptor_ops::ioctl(impl.descriptor_, -              FIONBIO, &non_blocking, ec)) -          return 0; -        impl.flags_ |= implementation_type::internal_non_blocking; -      } -    } -      // Send the data.      for (;;)      {        // Try to complete the operation without blocking.        int bytes_sent = descriptor_ops::gather_write( -          impl.descriptor_, bufs, i, ec); +          impl.descriptor_, bufs.buffers(), bufs.count(), ec);        // Check if operation succeeded.        if (bytes_sent >= 0) @@ -310,48 +302,31 @@ public:      return 0;    } -  template <typename ConstBufferSequence, typename Handler> -  class write_operation : -    public handler_base_from_member<Handler> +  template <typename ConstBufferSequence> +  class write_op_base : public reactor_op    {    public: -    write_operation(int descriptor, boost::asio::io_service& io_service, -        const ConstBufferSequence& buffers, Handler handler) -      : handler_base_from_member<Handler>(handler), +    write_op_base(int descriptor, +        const ConstBufferSequence& buffers, func_type complete_func) +      : reactor_op(&write_op_base::do_perform, complete_func),          descriptor_(descriptor), -        io_service_(io_service), -        work_(io_service),          buffers_(buffers)      {      } -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -      { -        bytes_transferred = 0; -        return true; -      } +      write_op_base* o(static_cast<write_op_base*>(base)); -      // Copy buffers into array. -      descriptor_ops::buf bufs[max_buffers]; -      typename ConstBufferSequence::const_iterator iter = buffers_.begin(); -      typename ConstBufferSequence::const_iterator end = buffers_.end(); -      size_t i = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::const_buffer buffer(*iter); -        descriptor_ops::init_buf(bufs[i], -            boost::asio::buffer_cast<const void*>(buffer), -            boost::asio::buffer_size(buffer)); -      } +      buffer_sequence_adapter<boost::asio::const_buffer, +          ConstBufferSequence> bufs(o->buffers_);        for (;;)        {          // Write the data. -        int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec); +        boost::system::error_code ec; +        int bytes = descriptor_ops::gather_write( +            o->descriptor_, bufs.buffers(), bufs.count(), ec);          // Retry operation if interrupted by signal.          if (ec == boost::asio::error::interrupted) @@ -362,120 +337,89 @@ public:              || ec == boost::asio::error::try_again)            return false; -        bytes_transferred = (bytes < 0 ? 0 : bytes); +        o->ec_ = ec; +        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);          return true;        }      } -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); -    } -    private:      int descriptor_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      ConstBufferSequence buffers_;    }; -  // Start an asynchronous write. The data being sent must be valid for the -  // lifetime of the asynchronous operation.    template <typename ConstBufferSequence, typename Handler> -  void async_write_some(implementation_type& impl, -      const ConstBufferSequence& buffers, Handler handler) -  { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      // Determine total size of buffers. -      typename ConstBufferSequence::const_iterator iter = buffers.begin(); -      typename ConstBufferSequence::const_iterator end = buffers.end(); -      size_t i = 0; -      size_t total_buffer_size = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::const_buffer buffer(*iter); -        total_buffer_size += boost::asio::buffer_size(buffer); -      } - -      // A request to read_some 0 bytes on a stream is a no-op. -      if (total_buffer_size == 0) -      { -        this->get_io_service().post(bind_handler(handler, -              boost::system::error_code(), 0)); -        return; -      } - -      // Make descriptor non-blocking. -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) -      { -        ioctl_arg_type non_blocking = 1; -        boost::system::error_code ec; -        if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) -        { -          this->get_io_service().post(bind_handler(handler, ec, 0)); -          return; -        } -        impl.flags_ |= implementation_type::internal_non_blocking; -      } - -      reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, -          write_operation<ConstBufferSequence, Handler>( -            impl.descriptor_, this->get_io_service(), buffers, handler)); -    } -  } - -  template <typename Handler> -  class null_buffers_operation : -    public handler_base_from_member<Handler> +  class write_op : public write_op_base<ConstBufferSequence>    {    public: -    null_buffers_operation(boost::asio::io_service& io_service, Handler handler) -      : handler_base_from_member<Handler>(handler), -        work_(io_service) +    write_op(int descriptor, +        const ConstBufferSequence& buffers, Handler handler) +      : write_op_base<ConstBufferSequence>( +          descriptor, buffers, &write_op::do_complete), +        handler_(handler)      {      } -    bool perform(boost::system::error_code&, -        std::size_t& bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)      { -      bytes_transferred = 0; -      return true; -    } +      // Take ownership of the handler object. +      write_op* o(static_cast<write_op*>(base)); +      typedef handler_alloc_traits<Handler, write_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      work_.get_io_service().post(bind_handler( -            this->handler_, ec, bytes_transferred)); +      // Make the upcall if required. +      if (owner) +      { +        // 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, std::size_t> +          handler(o->handler_, o->ec_, o->bytes_transferred_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      }    private: -    boost::asio::io_service::work work_; +    Handler handler_;    }; +  // Start an asynchronous write. The data being sent must be valid for the +  // lifetime of the asynchronous operation. +  template <typename ConstBufferSequence, typename Handler> +  void async_write_some(implementation_type& impl, +      const ConstBufferSequence& buffers, Handler handler) +  { +    // Allocate and construct an operation to wrap the handler. +    typedef write_op<ConstBufferSequence, 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.descriptor_, buffers, handler); + +    start_op(impl, reactor::write_op, ptr.get(), true, +        buffer_sequence_adapter<boost::asio::const_buffer, +          ConstBufferSequence>::all_empty(buffers)); +    ptr.release(); +  } +    // Start an asynchronous wait until data can be written without blocking.    template <typename Handler>    void async_write_some(implementation_type& impl,        const null_buffers&, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler), -          false); -    } +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); + +    start_op(impl, reactor::write_op, ptr.get(), false, false); +    ptr.release();    }    // Read some data from the stream. Returns the number of bytes read. @@ -489,46 +433,22 @@ public:        return 0;      } -    // Copy buffers into array. -    descriptor_ops::buf bufs[max_buffers]; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    size_t i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::mutable_buffer buffer(*iter); -      descriptor_ops::init_buf(bufs[i], -          boost::asio::buffer_cast<void*>(buffer), -          boost::asio::buffer_size(buffer)); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } +    buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence> bufs(buffers);      // A request to read_some 0 bytes on a stream is a no-op. -    if (total_buffer_size == 0) +    if (bufs.all_empty())      {        ec = boost::system::error_code();        return 0;      } -    // Make descriptor non-blocking if user wants non-blocking. -    if (impl.flags_ & implementation_type::user_set_non_blocking) -    { -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) -      { -        ioctl_arg_type non_blocking = 1; -        if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) -          return 0; -        impl.flags_ |= implementation_type::internal_non_blocking; -      } -    } -      // Read some data.      for (;;)      {        // Try to complete the operation without blocking.        int bytes_read = descriptor_ops::scatter_read( -          impl.descriptor_, bufs, i, ec); +          impl.descriptor_, bufs.buffers(), bufs.count(), ec);        // Check if operation succeeded.        if (bytes_read > 0) @@ -569,48 +489,31 @@ public:      return 0;    } -  template <typename MutableBufferSequence, typename Handler> -  class read_operation : -    public handler_base_from_member<Handler> +  template <typename MutableBufferSequence> +  class read_op_base : public reactor_op    {    public: -    read_operation(int descriptor, boost::asio::io_service& io_service, -        const MutableBufferSequence& buffers, Handler handler) -      : handler_base_from_member<Handler>(handler), +    read_op_base(int descriptor, +        const MutableBufferSequence& buffers, func_type complete_func) +      : reactor_op(&read_op_base::do_perform, complete_func),          descriptor_(descriptor), -        io_service_(io_service), -        work_(io_service),          buffers_(buffers)      {      } -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -      { -        bytes_transferred = 0; -        return true; -      } +      read_op_base* o(static_cast<read_op_base*>(base)); -      // Copy buffers into array. -      descriptor_ops::buf bufs[max_buffers]; -      typename MutableBufferSequence::const_iterator iter = buffers_.begin(); -      typename MutableBufferSequence::const_iterator end = buffers_.end(); -      size_t i = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::mutable_buffer buffer(*iter); -        descriptor_ops::init_buf(bufs[i], -            boost::asio::buffer_cast<void*>(buffer), -            boost::asio::buffer_size(buffer)); -      } +      buffer_sequence_adapter<boost::asio::mutable_buffer, +          MutableBufferSequence> bufs(o->buffers_);        for (;;)        {          // Read some data. -        int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec); +        boost::system::error_code ec; +        int bytes = descriptor_ops::scatter_read( +            o->descriptor_, bufs.buffers(), bufs.count(), ec);          if (bytes == 0)            ec = boost::asio::error::eof; @@ -623,73 +526,75 @@ public:              || ec == boost::asio::error::try_again)            return false; -        bytes_transferred = (bytes < 0 ? 0 : bytes); +        o->ec_ = ec; +        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);          return true;        }      } -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); -    } -    private:      int descriptor_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      MutableBufferSequence buffers_;    }; -  // Start an asynchronous read. The buffer for the data being read must be -  // valid for the lifetime of the asynchronous operation.    template <typename MutableBufferSequence, typename Handler> -  void async_read_some(implementation_type& impl, -      const MutableBufferSequence& buffers, Handler handler) +  class read_op : public read_op_base<MutableBufferSequence>    { -    if (!is_open(impl)) +  public: +    read_op(int descriptor, +        const MutableBufferSequence& buffers, Handler handler) +      : read_op_base<MutableBufferSequence>( +          descriptor, buffers, &read_op::do_complete), +        handler_(handler)      { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0));      } -    else + +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)      { -      // Determine total size of buffers. -      typename MutableBufferSequence::const_iterator iter = buffers.begin(); -      typename MutableBufferSequence::const_iterator end = buffers.end(); -      size_t i = 0; -      size_t total_buffer_size = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::mutable_buffer buffer(*iter); -        total_buffer_size += boost::asio::buffer_size(buffer); -      } +      // Take ownership of the handler object. +      read_op* o(static_cast<read_op*>(base)); +      typedef handler_alloc_traits<Handler, read_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -      // A request to read_some 0 bytes on a stream is a no-op. -      if (total_buffer_size == 0) +      // Make the upcall if required. +      if (owner)        { -        this->get_io_service().post(bind_handler(handler, -              boost::system::error_code(), 0)); -        return; +        // 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, std::size_t> +          handler(o->handler_, o->ec_, o->bytes_transferred_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler);        } +    } -      // Make descriptor non-blocking. -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) -      { -        ioctl_arg_type non_blocking = 1; -        boost::system::error_code ec; -        if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) -        { -          this->get_io_service().post(bind_handler(handler, ec, 0)); -          return; -        } -        impl.flags_ |= implementation_type::internal_non_blocking; -      } +  private: +    Handler handler_; +  }; -      reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, -          read_operation<MutableBufferSequence, Handler>( -            impl.descriptor_, this->get_io_service(), buffers, handler)); -    } +  // Start an asynchronous read. The buffer for the data being read must be +  // valid for the lifetime of the asynchronous operation. +  template <typename MutableBufferSequence, typename Handler> +  void async_read_some(implementation_type& impl, +      const MutableBufferSequence& buffers, Handler handler) +  { +    // Allocate and construct an operation to wrap the handler. +    typedef read_op<MutableBufferSequence, 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.descriptor_, buffers, handler); + +    start_op(impl, reactor::read_op, ptr.get(), true, +        buffer_sequence_adapter<boost::asio::mutable_buffer, +          MutableBufferSequence>::all_empty(buffers)); +    ptr.release();    }    // Wait until data can be read without blocking. @@ -697,22 +602,61 @@ public:    void async_read_some(implementation_type& impl,        const null_buffers&, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); + +    start_op(impl, reactor::read_op, ptr.get(), false, false); +    ptr.release(); +  } + +private: +  // Start the asynchronous operation. +  void start_op(implementation_type& impl, int op_type, +      reactor_op* op, bool non_blocking, bool noop) +  { +    if (!noop)      { -      reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler), -          false); +      if (is_open(impl)) +      { +        if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_)) +        { +          reactor_.start_op(op_type, impl.descriptor_, +              impl.reactor_data_, op, non_blocking); +          return; +        } +      } +      else +        op->ec_ = boost::asio::error::bad_descriptor;      } + +    io_service_impl_.post_immediate_completion(op);    } -private: +  // Determine whether the descriptor has been set non-blocking. +  bool is_non_blocking(implementation_type& impl) const +  { +    return (impl.flags_ & implementation_type::non_blocking); +  } + +  // Set the internal non-blocking flag. +  bool set_non_blocking(implementation_type& impl, +      boost::system::error_code& ec) +  { +    ioctl_arg_type non_blocking = 1; +    if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) +      return false; +    impl.flags_ |= implementation_type::internal_non_blocking; +    return true; +  } + +  // The io_service implementation used to post completions. +  io_service_impl& io_service_impl_; +    // The selector that performs event demultiplexing for the service. -  Reactor& reactor_; +  reactor& reactor_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/reactive_serial_port_service.hpp b/3rdParty/Boost/src/boost/asio/detail/reactive_serial_port_service.hpp index cd163e9..faa2149 100644 --- a/3rdParty/Boost/src/boost/asio/detail/reactive_serial_port_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/reactive_serial_port_service.hpp @@ -38,31 +38,24 @@ namespace asio {  namespace detail {  // Extend reactive_descriptor_service to provide serial port support. -template <typename Reactor>  class reactive_serial_port_service -  : public boost::asio::detail::service_base< -      reactive_serial_port_service<Reactor> >  {  public: -  // The native type of a stream handle. -  typedef typename reactive_descriptor_service<Reactor>::native_type -    native_type; +  // The native type of a serial port. +  typedef reactive_descriptor_service::native_type native_type; -  // The implementation type of the stream handle. -  typedef typename reactive_descriptor_service<Reactor>::implementation_type -    implementation_type; +  // The implementation type of the serial port. +  typedef reactive_descriptor_service::implementation_type implementation_type;    reactive_serial_port_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        reactive_serial_port_service>(io_service), -      descriptor_service_(boost::asio::use_service< -          reactive_descriptor_service<Reactor> >(io_service)) +    : descriptor_service_(io_service)    {    }    // Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    descriptor_service_.shutdown_service();    }    // Construct a new handle implementation. @@ -254,8 +247,8 @@ public:    }  private: -  // The handle service used for initiating asynchronous operations. -  reactive_descriptor_service<Reactor>& descriptor_service_; +  // The implementation used for initiating asynchronous operations. +  reactive_descriptor_service descriptor_service_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/reactive_socket_service.hpp b/3rdParty/Boost/src/boost/asio/detail/reactive_socket_service.hpp index 95d39dd..5f7bbf5 100644 --- a/3rdParty/Boost/src/boost/asio/detail/reactive_socket_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/reactive_socket_service.hpp @@ -17,18 +17,17 @@  #include <boost/asio/detail/push_options.hpp> -#include <boost/asio/detail/push_options.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/asio/detail/pop_options.hpp> -  #include <boost/asio/buffer.hpp>  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp>  #include <boost/asio/socket_base.hpp>  #include <boost/asio/detail/bind_handler.hpp> -#include <boost/asio/detail/handler_base_from_member.hpp> +#include <boost/asio/detail/buffer_sequence_adapter.hpp> +#include <boost/asio/detail/fenced_block.hpp>  #include <boost/asio/detail/noncopyable.hpp> -#include <boost/asio/detail/service_base.hpp> +#include <boost/asio/detail/null_buffers_op.hpp> +#include <boost/asio/detail/reactor.hpp> +#include <boost/asio/detail/reactor_op.hpp>  #include <boost/asio/detail/socket_holder.hpp>  #include <boost/asio/detail/socket_ops.hpp>  #include <boost/asio/detail/socket_types.hpp> @@ -37,10 +36,8 @@ namespace boost {  namespace asio {  namespace detail { -template <typename Protocol, typename Reactor> +template <typename Protocol>  class reactive_socket_service -  : public boost::asio::detail::service_base< -      reactive_socket_service<Protocol, Reactor> >  {  public:    // The protocol type. @@ -67,7 +64,7 @@ public:    private:      // Only this service will have access to the internal values. -    friend class reactive_socket_service<Protocol, Reactor>; +    friend class reactive_socket_service<Protocol>;      // The native socket representation.      socket_type socket_; @@ -87,7 +84,7 @@ public:        // User wants connection_aborted errors, which are disabled by default.        enable_connection_aborted = 4, -      // The user set the linger option. Needs to be checked when closing.  +      // The user set the linger option. Needs to be checked when closing.        user_set_linger = 8      }; @@ -98,17 +95,13 @@ public:      protocol_type protocol_;      // Per-descriptor data used by the reactor. -    typename Reactor::per_descriptor_data reactor_data_; +    reactor::per_descriptor_data reactor_data_;    }; -  // The maximum number of buffers to support in a single operation. -  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; -    // Constructor.    reactive_socket_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        reactive_socket_service<Protocol, Reactor> >(io_service), -      reactor_(boost::asio::use_service<Reactor>(io_service)) +    : io_service_impl_(use_service<io_service_impl>(io_service)), +      reactor_(use_service<reactor>(io_service))    {      reactor_.init_task();    } @@ -452,43 +445,30 @@ public:        return ec;      } -    if (command.name() == static_cast<int>(FIONBIO)) +    socket_ops::ioctl(impl.socket_, command.name(), +        static_cast<ioctl_arg_type*>(command.data()), ec); + +    // When updating the non-blocking mode we always perform the ioctl +    // syscall, even if the flags would otherwise indicate that the socket is +    // already in the correct state. This ensures that the underlying socket +    // is put into the state that has been requested by the user. If the ioctl +    // syscall was successful then we need to update the flags to match. +    if (!ec && command.name() == static_cast<int>(FIONBIO))      { -      // Flags are manipulated in a temporary variable so that the socket -      // implementation is not updated unless the ioctl operation succeeds. -      unsigned char new_flags = impl.flags_;        if (*static_cast<ioctl_arg_type*>(command.data())) -        new_flags |= implementation_type::user_set_non_blocking; -      else -        new_flags &= ~implementation_type::user_set_non_blocking; - -      // Perform ioctl on socket if the non-blocking state has changed. -      if (!(impl.flags_ & implementation_type::non_blocking) -          && (new_flags & implementation_type::non_blocking))        { -        ioctl_arg_type non_blocking = 1; -        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec); -      } -      else if ((impl.flags_ & implementation_type::non_blocking) -          && !(new_flags & implementation_type::non_blocking)) -      { -        ioctl_arg_type non_blocking = 0; -        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec); +        impl.flags_ |= implementation_type::user_set_non_blocking;        }        else        { -        ec = boost::system::error_code(); +        // Clearing the non-blocking mode always overrides any internally-set +        // non-blocking flag. Any subsequent asynchronous operations will need +        // to re-enable non-blocking I/O. +        impl.flags_ &= ~(implementation_type::user_set_non_blocking +            | implementation_type::internal_non_blocking);        } - -      // Update socket implementation's flags only if successful. -      if (!ec) -        impl.flags_ = new_flags; -    } -    else -    { -      socket_ops::ioctl(impl.socket_, command.name(), -          static_cast<ioctl_arg_type*>(command.data()), ec);      } +      return ec;    } @@ -553,23 +533,11 @@ public:        return 0;      } -    // Copy buffers into array. -    socket_ops::buf bufs[max_buffers]; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    size_t i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::const_buffer buffer(*iter); -      socket_ops::init_buf(bufs[i], -          boost::asio::buffer_cast<const void*>(buffer), -          boost::asio::buffer_size(buffer)); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } +    buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence> bufs(buffers);      // A request to receive 0 bytes on a stream socket is a no-op. -    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) +    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())      {        ec = boost::system::error_code();        return 0; @@ -579,7 +547,8 @@ public:      for (;;)      {        // Try to complete the operation without blocking. -      int bytes_sent = socket_ops::send(impl.socket_, bufs, i, flags, ec); +      int bytes_sent = socket_ops::send(impl.socket_, +          bufs.buffers(), bufs.count(), flags, ec);        // Check if operation succeeded.        if (bytes_sent >= 0) @@ -613,50 +582,32 @@ public:      return 0;    } -  template <typename ConstBufferSequence, typename Handler> -  class send_operation : -    public handler_base_from_member<Handler> +  template <typename ConstBufferSequence> +  class send_op_base : public reactor_op    {    public: -    send_operation(socket_type socket, boost::asio::io_service& io_service, -        const ConstBufferSequence& buffers, socket_base::message_flags flags, -        Handler handler) -      : handler_base_from_member<Handler>(handler), +    send_op_base(socket_type socket, const ConstBufferSequence& buffers, +        socket_base::message_flags flags, func_type complete_func) +      : reactor_op(&send_op_base::do_perform, complete_func),          socket_(socket), -        io_service_(io_service), -        work_(io_service),          buffers_(buffers),          flags_(flags)      {      } -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -      { -        bytes_transferred = 0; -        return true; -      } +      send_op_base* o(static_cast<send_op_base*>(base)); -      // Copy buffers into array. -      socket_ops::buf bufs[max_buffers]; -      typename ConstBufferSequence::const_iterator iter = buffers_.begin(); -      typename ConstBufferSequence::const_iterator end = buffers_.end(); -      size_t i = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::const_buffer buffer(*iter); -        socket_ops::init_buf(bufs[i], -            boost::asio::buffer_cast<const void*>(buffer), -            boost::asio::buffer_size(buffer)); -      } +      buffer_sequence_adapter<boost::asio::const_buffer, +          ConstBufferSequence> bufs(o->buffers_);        for (;;)        {          // Send the data. -        int bytes = socket_ops::send(socket_, bufs, i, flags_, ec); +        boost::system::error_code ec; +        int bytes = socket_ops::send(o->socket_, +            bufs.buffers(), bufs.count(), o->flags_, ec);          // Retry operation if interrupted by signal.          if (ec == boost::asio::error::interrupted) @@ -667,127 +618,92 @@ public:              || ec == boost::asio::error::try_again)            return false; -        bytes_transferred = (bytes < 0 ? 0 : bytes); +        o->ec_ = ec; +        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);          return true;        }      } -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); -    } -    private:      socket_type socket_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      ConstBufferSequence buffers_;      socket_base::message_flags flags_;    }; -  // Start an asynchronous send. The data being sent must be valid for the -  // lifetime of the asynchronous operation.    template <typename ConstBufferSequence, typename Handler> -  void async_send(implementation_type& impl, const ConstBufferSequence& buffers, -      socket_base::message_flags flags, Handler handler) -  { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      if (impl.protocol_.type() == SOCK_STREAM) -      { -        // Determine total size of buffers. -        typename ConstBufferSequence::const_iterator iter = buffers.begin(); -        typename ConstBufferSequence::const_iterator end = buffers.end(); -        size_t i = 0; -        size_t total_buffer_size = 0; -        for (; iter != end && i < max_buffers; ++iter, ++i) -        { -          boost::asio::const_buffer buffer(*iter); -          total_buffer_size += boost::asio::buffer_size(buffer); -        } - -        // A request to receive 0 bytes on a stream socket is a no-op. -        if (total_buffer_size == 0) -        { -          this->get_io_service().post(bind_handler(handler, -                boost::system::error_code(), 0)); -          return; -        } -      } - -      // Make socket non-blocking. -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) -      { -        if (!(impl.flags_ & implementation_type::non_blocking)) -        { -          ioctl_arg_type non_blocking = 1; -          boost::system::error_code ec; -          if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) -          { -            this->get_io_service().post(bind_handler(handler, ec, 0)); -            return; -          } -        } -        impl.flags_ |= implementation_type::internal_non_blocking; -      } - -      reactor_.start_write_op(impl.socket_, impl.reactor_data_, -          send_operation<ConstBufferSequence, Handler>( -            impl.socket_, this->get_io_service(), buffers, flags, handler)); -    } -  } - -  template <typename Handler> -  class null_buffers_operation : -    public handler_base_from_member<Handler> +  class send_op : public send_op_base<ConstBufferSequence>    {    public: -    null_buffers_operation(boost::asio::io_service& io_service, Handler handler) -      : handler_base_from_member<Handler>(handler), -        work_(io_service) +    send_op(socket_type socket, const ConstBufferSequence& buffers, +        socket_base::message_flags flags, Handler handler) +      : send_op_base<ConstBufferSequence>(socket, +          buffers, flags, &send_op::do_complete), +        handler_(handler)      {      } -    bool perform(boost::system::error_code&, -        std::size_t& bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)      { -      bytes_transferred = 0; -      return true; -    } +      // Take ownership of the handler object. +      send_op* o(static_cast<send_op*>(base)); +      typedef handler_alloc_traits<Handler, send_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      work_.get_io_service().post(bind_handler( -            this->handler_, ec, bytes_transferred)); +      // Make the upcall if required. +      if (owner) +      { +        // 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, std::size_t> +          handler(o->handler_, o->ec_, o->bytes_transferred_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      }    private: -    boost::asio::io_service::work work_; +    Handler handler_;    }; +  // Start an asynchronous send. The data being sent must be valid for the +  // lifetime of the asynchronous operation. +  template <typename ConstBufferSequence, typename Handler> +  void async_send(implementation_type& impl, const ConstBufferSequence& buffers, +      socket_base::message_flags flags, Handler handler) +  { +    // Allocate and construct an operation to wrap the handler. +    typedef send_op<ConstBufferSequence, 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.socket_, buffers, flags, handler); + +    start_op(impl, reactor::write_op, ptr.get(), true, +        (impl.protocol_.type() == SOCK_STREAM +          && buffer_sequence_adapter<boost::asio::const_buffer, +            ConstBufferSequence>::all_empty(buffers))); +    ptr.release(); +  } +    // Start an asynchronous wait until data can be sent without blocking.    template <typename Handler>    void async_send(implementation_type& impl, const null_buffers&,        socket_base::message_flags, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      reactor_.start_write_op(impl.socket_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler), -          false); -    } +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); + +    start_op(impl, reactor::write_op, ptr.get(), false, false); +    ptr.release();    }    // Send a datagram to the specified endpoint. Returns the number of bytes @@ -803,25 +719,15 @@ public:        return 0;      } -    // Copy buffers into array. -    socket_ops::buf bufs[max_buffers]; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    size_t i = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::const_buffer buffer(*iter); -      socket_ops::init_buf(bufs[i], -          boost::asio::buffer_cast<const void*>(buffer), -          boost::asio::buffer_size(buffer)); -    } +    buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence> bufs(buffers);      // Send the data.      for (;;)      {        // Try to complete the operation without blocking. -      int bytes_sent = socket_ops::sendto(impl.socket_, bufs, i, flags, -          destination.data(), destination.size(), ec); +      int bytes_sent = socket_ops::sendto(impl.socket_, bufs.buffers(), +          bufs.count(), flags, destination.data(), destination.size(), ec);        // Check if operation succeeded.        if (bytes_sent >= 0) @@ -856,52 +762,34 @@ public:      return 0;    } -  template <typename ConstBufferSequence, typename Handler> -  class send_to_operation : -    public handler_base_from_member<Handler> +  template <typename ConstBufferSequence> +  class send_to_op_base : public reactor_op    {    public: -    send_to_operation(socket_type socket, boost::asio::io_service& io_service, -        const ConstBufferSequence& buffers, const endpoint_type& endpoint, -        socket_base::message_flags flags, Handler handler) -      : handler_base_from_member<Handler>(handler), +    send_to_op_base(socket_type socket, const ConstBufferSequence& buffers, +        const endpoint_type& endpoint, socket_base::message_flags flags, +        func_type complete_func) +      : reactor_op(&send_to_op_base::do_perform, complete_func),          socket_(socket), -        io_service_(io_service), -        work_(io_service),          buffers_(buffers),          destination_(endpoint),          flags_(flags)      {      } -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -      { -        bytes_transferred = 0; -        return true; -      } +      send_to_op_base* o(static_cast<send_to_op_base*>(base)); -      // Copy buffers into array. -      socket_ops::buf bufs[max_buffers]; -      typename ConstBufferSequence::const_iterator iter = buffers_.begin(); -      typename ConstBufferSequence::const_iterator end = buffers_.end(); -      size_t i = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::const_buffer buffer(*iter); -        socket_ops::init_buf(bufs[i], -            boost::asio::buffer_cast<const void*>(buffer), -            boost::asio::buffer_size(buffer)); -      } +      buffer_sequence_adapter<boost::asio::const_buffer, +          ConstBufferSequence> bufs(o->buffers_);        for (;;)        {          // Send the data. -        int bytes = socket_ops::sendto(socket_, bufs, i, flags_, -            destination_.data(), destination_.size(), ec); +        boost::system::error_code ec; +        int bytes = socket_ops::sendto(o->socket_, bufs.buffers(), bufs.count(), +            o->flags_, o->destination_.data(), o->destination_.size(), ec);          // Retry operation if interrupted by signal.          if (ec == boost::asio::error::interrupted) @@ -912,62 +800,78 @@ public:              || ec == boost::asio::error::try_again)            return false; -        bytes_transferred = (bytes < 0 ? 0 : bytes); +        o->ec_ = ec; +        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);          return true;        }      } -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); -    } -    private:      socket_type socket_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      ConstBufferSequence buffers_;      endpoint_type destination_;      socket_base::message_flags flags_;    }; -  // Start an asynchronous send. The data being sent must be valid for the -  // lifetime of the asynchronous operation.    template <typename ConstBufferSequence, typename Handler> -  void async_send_to(implementation_type& impl, -      const ConstBufferSequence& buffers, -      const endpoint_type& destination, socket_base::message_flags flags, -      Handler handler) +  class send_to_op : public send_to_op_base<ConstBufferSequence>    { -    if (!is_open(impl)) +  public: +    send_to_op(socket_type socket, const ConstBufferSequence& buffers, +        const endpoint_type& endpoint, socket_base::message_flags flags, +        Handler handler) +      : send_to_op_base<ConstBufferSequence>(socket, +          buffers, endpoint, flags, &send_to_op::do_complete), +        handler_(handler)      { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0));      } -    else + +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)      { -      // Make socket non-blocking. -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) +      // Take ownership of the handler object. +      send_to_op* o(static_cast<send_to_op*>(base)); +      typedef handler_alloc_traits<Handler, send_to_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); + +      // Make the upcall if required. +      if (owner)        { -        if (!(impl.flags_ & implementation_type::non_blocking)) -        { -          ioctl_arg_type non_blocking = 1; -          boost::system::error_code ec; -          if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) -          { -            this->get_io_service().post(bind_handler(handler, ec, 0)); -            return; -          } -        } -        impl.flags_ |= implementation_type::internal_non_blocking; +        // 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, std::size_t> +          handler(o->handler_, o->ec_, o->bytes_transferred_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler);        } - -      reactor_.start_write_op(impl.socket_, impl.reactor_data_, -          send_to_operation<ConstBufferSequence, Handler>( -            impl.socket_, this->get_io_service(), buffers, -            destination, flags, handler));      } + +  private: +    Handler handler_; +  }; + +  // Start an asynchronous send. The data being sent must be valid for the +  // lifetime of the asynchronous operation. +  template <typename ConstBufferSequence, typename Handler> +  void async_send_to(implementation_type& impl, +      const ConstBufferSequence& buffers, +      const endpoint_type& destination, socket_base::message_flags flags, +      Handler handler) +  { +    // Allocate and construct an operation to wrap the handler. +    typedef send_to_op<ConstBufferSequence, 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.socket_, +        buffers, destination, flags, handler); + +    start_op(impl, reactor::write_op, ptr.get(), true, false); +    ptr.release();    }    // Start an asynchronous wait until data can be sent without blocking. @@ -975,17 +879,14 @@ public:    void async_send_to(implementation_type& impl, const null_buffers&,        socket_base::message_flags, const endpoint_type&, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      reactor_.start_write_op(impl.socket_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler), -          false); -    } +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); + +    start_op(impl, reactor::write_op, ptr.get(), false, false); +    ptr.release();    }    // Receive some data from the peer. Returns the number of bytes received. @@ -1000,23 +901,11 @@ public:        return 0;      } -    // Copy buffers into array. -    socket_ops::buf bufs[max_buffers]; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    size_t i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::mutable_buffer buffer(*iter); -      socket_ops::init_buf(bufs[i], -          boost::asio::buffer_cast<void*>(buffer), -          boost::asio::buffer_size(buffer)); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } +    buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence> bufs(buffers);      // A request to receive 0 bytes on a stream socket is a no-op. -    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) +    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())      {        ec = boost::system::error_code();        return 0; @@ -1026,7 +915,8 @@ public:      for (;;)      {        // Try to complete the operation without blocking. -      int bytes_recvd = socket_ops::recv(impl.socket_, bufs, i, flags, ec); +      int bytes_recvd = socket_ops::recv(impl.socket_, +          bufs.buffers(), bufs.count(), flags, ec);        // Check if operation succeeded.        if (bytes_recvd > 0) @@ -1067,53 +957,35 @@ public:      return 0;    } -  template <typename MutableBufferSequence, typename Handler> -  class receive_operation : -    public handler_base_from_member<Handler> +  template <typename MutableBufferSequence> +  class receive_op_base : public reactor_op    {    public: -    receive_operation(socket_type socket, int protocol_type, -        boost::asio::io_service& io_service, +    receive_op_base(socket_type socket, int protocol_type,          const MutableBufferSequence& buffers, -        socket_base::message_flags flags, Handler handler) -      : handler_base_from_member<Handler>(handler), +        socket_base::message_flags flags, func_type complete_func) +      : reactor_op(&receive_op_base::do_perform, complete_func),          socket_(socket),          protocol_type_(protocol_type), -        io_service_(io_service), -        work_(io_service),          buffers_(buffers),          flags_(flags)      {      } -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -      { -        bytes_transferred = 0; -        return true; -      } +      receive_op_base* o(static_cast<receive_op_base*>(base)); -      // Copy buffers into array. -      socket_ops::buf bufs[max_buffers]; -      typename MutableBufferSequence::const_iterator iter = buffers_.begin(); -      typename MutableBufferSequence::const_iterator end = buffers_.end(); -      size_t i = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::mutable_buffer buffer(*iter); -        socket_ops::init_buf(bufs[i], -            boost::asio::buffer_cast<void*>(buffer), -            boost::asio::buffer_size(buffer)); -      } +      buffer_sequence_adapter<boost::asio::mutable_buffer, +          MutableBufferSequence> bufs(o->buffers_);        for (;;)        {          // Receive some data. -        int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec); -        if (bytes == 0 && protocol_type_ == SOCK_STREAM) +        boost::system::error_code ec; +        int bytes = socket_ops::recv(o->socket_, +            bufs.buffers(), bufs.count(), o->flags_, ec); +        if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)            ec = boost::asio::error::eof;          // Retry operation if interrupted by signal. @@ -1125,93 +997,84 @@ public:              || ec == boost::asio::error::try_again)            return false; -        bytes_transferred = (bytes < 0 ? 0 : bytes); +        o->ec_ = ec; +        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);          return true;        }      } -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); -    } -    private:      socket_type socket_;      int protocol_type_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      MutableBufferSequence buffers_;      socket_base::message_flags flags_;    }; -  // Start an asynchronous receive. The buffer for the data being received -  // must be valid for the lifetime of the asynchronous operation.    template <typename MutableBufferSequence, typename Handler> -  void async_receive(implementation_type& impl, -      const MutableBufferSequence& buffers, -      socket_base::message_flags flags, Handler handler) +  class receive_op : public receive_op_base<MutableBufferSequence>    { -    if (!is_open(impl)) +  public: +    receive_op(socket_type socket, int protocol_type, +        const MutableBufferSequence& buffers, +        socket_base::message_flags flags, Handler handler) +      : receive_op_base<MutableBufferSequence>(socket, +          protocol_type, buffers, flags, &receive_op::do_complete), +        handler_(handler)      { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0));      } -    else -    { -      if (impl.protocol_.type() == SOCK_STREAM) -      { -        // Determine total size of buffers. -        typename MutableBufferSequence::const_iterator iter = buffers.begin(); -        typename MutableBufferSequence::const_iterator end = buffers.end(); -        size_t i = 0; -        size_t total_buffer_size = 0; -        for (; iter != end && i < max_buffers; ++iter, ++i) -        { -          boost::asio::mutable_buffer buffer(*iter); -          total_buffer_size += boost::asio::buffer_size(buffer); -        } - -        // A request to receive 0 bytes on a stream socket is a no-op. -        if (total_buffer_size == 0) -        { -          this->get_io_service().post(bind_handler(handler, -                boost::system::error_code(), 0)); -          return; -        } -      } -      // Make socket non-blocking. -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) -      { -        if (!(impl.flags_ & implementation_type::non_blocking)) -        { -          ioctl_arg_type non_blocking = 1; -          boost::system::error_code ec; -          if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) -          { -            this->get_io_service().post(bind_handler(handler, ec, 0)); -            return; -          } -        } -        impl.flags_ |= implementation_type::internal_non_blocking; -      } +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) +    { +      // Take ownership of the handler object. +      receive_op* o(static_cast<receive_op*>(base)); +      typedef handler_alloc_traits<Handler, receive_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -      if (flags & socket_base::message_out_of_band) +      // Make the upcall if required. +      if (owner)        { -        reactor_.start_except_op(impl.socket_, impl.reactor_data_, -            receive_operation<MutableBufferSequence, Handler>( -              impl.socket_, impl.protocol_.type(), -              this->get_io_service(), buffers, flags, handler)); -      } -      else -      { -        reactor_.start_read_op(impl.socket_, impl.reactor_data_, -            receive_operation<MutableBufferSequence, Handler>( -              impl.socket_, impl.protocol_.type(), -              this->get_io_service(), buffers, flags, handler)); +        // 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, std::size_t> +          handler(o->handler_, o->ec_, o->bytes_transferred_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler);        }      } + +  private: +    Handler handler_; +  }; + +  // Start an asynchronous receive. The buffer for the data being received +  // must be valid for the lifetime of the asynchronous operation. +  template <typename MutableBufferSequence, typename Handler> +  void async_receive(implementation_type& impl, +      const MutableBufferSequence& buffers, +      socket_base::message_flags flags, Handler handler) +  { +    // Allocate and construct an operation to wrap the handler. +    typedef receive_op<MutableBufferSequence, Handler> value_type; +    typedef handler_alloc_traits<Handler, value_type> alloc_traits; +    raw_handler_ptr<alloc_traits> raw_ptr(handler); +    int protocol_type = impl.protocol_.type(); +    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, +        protocol_type, buffers, flags, handler); + +    start_op(impl, +        (flags & socket_base::message_out_of_band) +          ? reactor::except_op : reactor::read_op, +        ptr.get(), (flags & socket_base::message_out_of_band) == 0, +        (impl.protocol_.type() == SOCK_STREAM +          && buffer_sequence_adapter<boost::asio::mutable_buffer, +            MutableBufferSequence>::all_empty(buffers))); +    ptr.release();    }    // Wait until data can be received without blocking. @@ -1219,22 +1082,17 @@ public:    void async_receive(implementation_type& impl, const null_buffers&,        socket_base::message_flags flags, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else if (flags & socket_base::message_out_of_band) -    { -      reactor_.start_except_op(impl.socket_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler)); -    } -    else -    { -      reactor_.start_read_op(impl.socket_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler), -          false); -    } +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); + +    start_op(impl, +        (flags & socket_base::message_out_of_band) +          ? reactor::except_op : reactor::read_op, +        ptr.get(), false, false); +    ptr.release();    }    // Receive a datagram with the endpoint of the sender. Returns the number of @@ -1251,26 +1109,16 @@ public:        return 0;      } -    // Copy buffers into array. -    socket_ops::buf bufs[max_buffers]; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    size_t i = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::mutable_buffer buffer(*iter); -      socket_ops::init_buf(bufs[i], -          boost::asio::buffer_cast<void*>(buffer), -          boost::asio::buffer_size(buffer)); -    } +    buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence> bufs(buffers);      // Receive some data.      for (;;)      {        // Try to complete the operation without blocking.        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); +      int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs.buffers(), +          bufs.count(), flags, sender_endpoint.data(), &addr_len, ec);        // Check if operation succeeded.        if (bytes_recvd > 0) @@ -1318,56 +1166,37 @@ public:      return 0;    } -  template <typename MutableBufferSequence, typename Handler> -  class receive_from_operation : -    public handler_base_from_member<Handler> +  template <typename MutableBufferSequence> +  class receive_from_op_base : public reactor_op    {    public: -    receive_from_operation(socket_type socket, int protocol_type, -        boost::asio::io_service& io_service, +    receive_from_op_base(socket_type socket, int protocol_type,          const MutableBufferSequence& buffers, endpoint_type& endpoint, -        socket_base::message_flags flags, Handler handler) -      : handler_base_from_member<Handler>(handler), +        socket_base::message_flags flags, func_type complete_func) +      : reactor_op(&receive_from_op_base::do_perform, complete_func),          socket_(socket),          protocol_type_(protocol_type), -        io_service_(io_service), -        work_(io_service),          buffers_(buffers),          sender_endpoint_(endpoint),          flags_(flags)      {      } -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -      { -        bytes_transferred = 0; -        return true; -      } +      receive_from_op_base* o(static_cast<receive_from_op_base*>(base)); -      // Copy buffers into array. -      socket_ops::buf bufs[max_buffers]; -      typename MutableBufferSequence::const_iterator iter = buffers_.begin(); -      typename MutableBufferSequence::const_iterator end = buffers_.end(); -      size_t i = 0; -      for (; iter != end && i < max_buffers; ++iter, ++i) -      { -        boost::asio::mutable_buffer buffer(*iter); -        socket_ops::init_buf(bufs[i], -            boost::asio::buffer_cast<void*>(buffer), -            boost::asio::buffer_size(buffer)); -      } +      buffer_sequence_adapter<boost::asio::mutable_buffer, +          MutableBufferSequence> bufs(o->buffers_);        for (;;)        {          // Receive some data. -        std::size_t addr_len = sender_endpoint_.capacity(); -        int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_, -            sender_endpoint_.data(), &addr_len, ec); -        if (bytes == 0 && protocol_type_ == SOCK_STREAM) +        boost::system::error_code ec; +        std::size_t addr_len = o->sender_endpoint_.capacity(); +        int bytes = socket_ops::recvfrom(o->socket_, bufs.buffers(), +            bufs.count(), o->flags_, o->sender_endpoint_.data(), &addr_len, ec); +        if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)            ec = boost::asio::error::eof;          // Retry operation if interrupted by signal. @@ -1379,64 +1208,84 @@ public:              || ec == boost::asio::error::try_again)            return false; -        sender_endpoint_.resize(addr_len); -        bytes_transferred = (bytes < 0 ? 0 : bytes); +        o->sender_endpoint_.resize(addr_len); +        o->ec_ = ec; +        o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);          return true;        }      } -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); -    } -    private:      socket_type socket_;      int protocol_type_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      MutableBufferSequence buffers_;      endpoint_type& sender_endpoint_;      socket_base::message_flags flags_;    }; -  // Start an asynchronous receive. The buffer for the data being received and -  // the sender_endpoint object must both be valid for the lifetime of the -  // asynchronous operation.    template <typename MutableBufferSequence, typename Handler> -  void async_receive_from(implementation_type& impl, -      const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, -      socket_base::message_flags flags, Handler handler) +  class receive_from_op : public receive_from_op_base<MutableBufferSequence>    { -    if (!is_open(impl)) +  public: +    receive_from_op(socket_type socket, int protocol_type, +        const MutableBufferSequence& buffers, endpoint_type& endpoint, +        socket_base::message_flags flags, Handler handler) +      : receive_from_op_base<MutableBufferSequence>(socket, protocol_type, +          buffers, endpoint, flags, &receive_from_op::do_complete), +        handler_(handler)      { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0));      } -    else + +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)      { -      // Make socket non-blocking. -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) +      // Take ownership of the handler object. +      receive_from_op* o(static_cast<receive_from_op*>(base)); +      typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); + +      // Make the upcall if required. +      if (owner)        { -        if (!(impl.flags_ & implementation_type::non_blocking)) -        { -          ioctl_arg_type non_blocking = 1; -          boost::system::error_code ec; -          if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) -          { -            this->get_io_service().post(bind_handler(handler, ec, 0)); -            return; -          } -        } -        impl.flags_ |= implementation_type::internal_non_blocking; +        // 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, std::size_t> +          handler(o->handler_, o->ec_, o->bytes_transferred_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler);        } - -      reactor_.start_read_op(impl.socket_, impl.reactor_data_, -          receive_from_operation<MutableBufferSequence, Handler>( -            impl.socket_, impl.protocol_.type(), this->get_io_service(), -            buffers, sender_endpoint, flags, handler));      } + +  private: +    Handler handler_; +  }; + +  // Start an asynchronous receive. The buffer for the data being received and +  // the sender_endpoint object must both be valid for the lifetime of the +  // asynchronous operation. +  template <typename MutableBufferSequence, typename Handler> +  void async_receive_from(implementation_type& impl, +      const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, +      socket_base::message_flags flags, Handler handler) +  { +    // Allocate and construct an operation to wrap the handler. +    typedef receive_from_op<MutableBufferSequence, Handler> value_type; +    typedef handler_alloc_traits<Handler, value_type> alloc_traits; +    raw_handler_ptr<alloc_traits> raw_ptr(handler); +    int protocol_type = impl.protocol_.type(); +    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, +        protocol_type, buffers, sender_endpoint, flags, handler); + +    start_op(impl, +        (flags & socket_base::message_out_of_band) +          ? reactor::except_op : reactor::read_op, +        ptr.get(), true, false); +    ptr.release();    }    // Wait until data can be received without blocking. @@ -1445,28 +1294,20 @@ public:        const null_buffers&, endpoint_type& sender_endpoint,        socket_base::message_flags flags, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      // Reset endpoint since it can be given no sensible value at this time. -      sender_endpoint = endpoint_type(); +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); -      if (flags & socket_base::message_out_of_band) -      { -        reactor_.start_except_op(impl.socket_, impl.reactor_data_, -            null_buffers_operation<Handler>(this->get_io_service(), handler)); -      } -      else -      { -        reactor_.start_read_op(impl.socket_, impl.reactor_data_, -            null_buffers_operation<Handler>(this->get_io_service(), handler), -            false); -      } -    } +    // Reset endpoint since it can be given no sensible value at this time. +    sender_endpoint = endpoint_type(); + +    start_op(impl, +        (flags & socket_base::message_out_of_band) +          ? reactor::except_op : reactor::read_op, +        ptr.get(), false, false); +    ptr.release();    }    // Accept a new connection. @@ -1546,19 +1387,15 @@ public:      }    } -  template <typename Socket, typename Handler> -  class accept_operation : -    public handler_base_from_member<Handler> +  template <typename Socket> +  class accept_op_base : public reactor_op    {    public: -    accept_operation(socket_type socket, boost::asio::io_service& io_service, -        Socket& peer, const protocol_type& protocol, -        endpoint_type* peer_endpoint, bool enable_connection_aborted, -        Handler handler) -      : handler_base_from_member<Handler>(handler), +    accept_op_base(socket_type socket, Socket& peer, +        const protocol_type& protocol, endpoint_type* peer_endpoint, +        bool enable_connection_aborted, func_type complete_func) +      : reactor_op(&accept_op_base::do_perform, complete_func),          socket_(socket), -        io_service_(io_service), -        work_(io_service),          peer_(peer),          protocol_(protocol),          peer_endpoint_(peer_endpoint), @@ -1566,27 +1403,25 @@ public:      {      } -    bool perform(boost::system::error_code& ec, std::size_t&) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -        return true; +      accept_op_base* o(static_cast<accept_op_base*>(base));        for (;;)        {          // Accept the waiting connection. +        boost::system::error_code ec;          socket_holder new_socket;          std::size_t addr_len = 0; -        if (peer_endpoint_) -        { -          addr_len = peer_endpoint_->capacity(); -          new_socket.reset(socket_ops::accept(socket_, -                peer_endpoint_->data(), &addr_len, ec)); -        } -        else +        std::size_t* addr_len_p = 0; +        socket_addr_type* addr = 0; +        if (o->peer_endpoint_)          { -          new_socket.reset(socket_ops::accept(socket_, 0, 0, ec)); +          addr_len = o->peer_endpoint_->capacity(); +          addr_len_p = &addr_len; +          addr = o->peer_endpoint_->data();          } +        new_socket.reset(socket_ops::accept(o->socket_, addr, addr_len_p, ec));          // Retry operation if interrupted by signal.          if (ec == boost::asio::error::interrupted) @@ -1597,83 +1432,95 @@ public:              || ec == boost::asio::error::try_again)            return false;          if (ec == boost::asio::error::connection_aborted -            && !enable_connection_aborted_) +            && !o->enable_connection_aborted_)            return false;  #if defined(EPROTO) -        if (ec.value() == EPROTO && !enable_connection_aborted_) +        if (ec.value() == EPROTO && !o->enable_connection_aborted_)            return false;  #endif // defined(EPROTO)          // Transfer ownership of the new socket to the peer object.          if (!ec)          { -          if (peer_endpoint_) -            peer_endpoint_->resize(addr_len); -          peer_.assign(protocol_, new_socket.get(), ec); +          if (o->peer_endpoint_) +            o->peer_endpoint_->resize(addr_len); +          o->peer_.assign(o->protocol_, new_socket.get(), ec);            if (!ec)              new_socket.release();          } +        o->ec_ = ec;          return true;        }      } -    void complete(const boost::system::error_code& ec, std::size_t) -    { -      io_service_.post(bind_handler(this->handler_, ec)); -    } -    private:      socket_type socket_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      Socket& peer_;      protocol_type protocol_;      endpoint_type* peer_endpoint_;      bool enable_connection_aborted_;    }; -  // Start an asynchronous accept. The peer and peer_endpoint objects -  // must be valid until the accept's handler is invoked.    template <typename Socket, typename Handler> -  void async_accept(implementation_type& impl, Socket& peer, -      endpoint_type* peer_endpoint, Handler handler) +  class accept_op : public accept_op_base<Socket>    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor)); -    } -    else if (peer.is_open()) +  public: +    accept_op(socket_type socket, Socket& peer, const protocol_type& protocol, +        endpoint_type* peer_endpoint, bool enable_connection_aborted, +        Handler handler) +      : accept_op_base<Socket>(socket, peer, protocol, peer_endpoint, +          enable_connection_aborted, &accept_op::do_complete), +        handler_(handler)      { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::already_open));      } -    else + +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)      { -      // Make socket non-blocking. -      if (!(impl.flags_ & implementation_type::internal_non_blocking)) +      // Take ownership of the handler object. +      accept_op* o(static_cast<accept_op*>(base)); +      typedef handler_alloc_traits<Handler, accept_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); + +      // Make the upcall if required. +      if (owner)        { -        if (!(impl.flags_ & implementation_type::non_blocking)) -        { -          ioctl_arg_type non_blocking = 1; -          boost::system::error_code ec; -          if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) -          { -            this->get_io_service().post(bind_handler(handler, ec)); -            return; -          } -        } -        impl.flags_ |= implementation_type::internal_non_blocking; +        // 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::binder1<Handler, boost::system::error_code> +          handler(o->handler_, o->ec_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler);        } - -      reactor_.start_read_op(impl.socket_, impl.reactor_data_, -          accept_operation<Socket, Handler>( -            impl.socket_, this->get_io_service(), -            peer, impl.protocol_, peer_endpoint, -            (impl.flags_ & implementation_type::enable_connection_aborted) != 0, -            handler));      } + +  private: +    Handler handler_; +  }; + +  // Start an asynchronous accept. The peer and peer_endpoint objects +  // must be valid until the accept's handler is invoked. +  template <typename Socket, typename Handler> +  void async_accept(implementation_type& impl, Socket& peer, +      endpoint_type* peer_endpoint, Handler handler) +  { +    // Allocate and construct an operation to wrap the handler. +    typedef accept_op<Socket, Handler> value_type; +    typedef handler_alloc_traits<Handler, value_type> alloc_traits; +    raw_handler_ptr<alloc_traits> raw_ptr(handler); +    bool enable_connection_aborted = +      (impl.flags_ & implementation_type::enable_connection_aborted) != 0; +    handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, peer, +        impl.protocol_, peer_endpoint, enable_connection_aborted, handler); + +    start_accept_op(impl, ptr.get(), peer.is_open()); +    ptr.release();    }    // Connect the socket to the specified endpoint. @@ -1713,53 +1560,77 @@ public:      return ec;    } -  template <typename Handler> -  class connect_operation : -    public handler_base_from_member<Handler> +  class connect_op_base : public reactor_op    {    public: -    connect_operation(socket_type socket, -        boost::asio::io_service& io_service, Handler handler) -      : handler_base_from_member<Handler>(handler), -        socket_(socket), -        io_service_(io_service), -        work_(io_service) +    connect_op_base(socket_type socket, func_type complete_func) +      : reactor_op(&connect_op_base::do_perform, complete_func), +        socket_(socket)      {      } -    bool perform(boost::system::error_code& ec, std::size_t&) +    static bool do_perform(reactor_op* base)      { -      // Check whether the operation was successful. -      if (ec) -        return true; +      connect_op_base* o(static_cast<connect_op_base*>(base));        // Get the error code from the connect operation.        int connect_error = 0;        size_t connect_error_len = sizeof(connect_error); -      if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, -            &connect_error, &connect_error_len, ec) == socket_error_retval) +      if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR, +            &connect_error, &connect_error_len, o->ec_) == socket_error_retval)          return true;        // The connection failed so the handler will be posted with an error code.        if (connect_error)        { -        ec = boost::system::error_code(connect_error, +        o->ec_ = boost::system::error_code(connect_error,              boost::asio::error::get_system_category()); -        return true;        }        return true;      } -    void complete(const boost::system::error_code& ec, std::size_t) +  private: +    socket_type socket_; +  }; + +  template <typename Handler> +  class connect_op : public connect_op_base +  { +  public: +    connect_op(socket_type socket, Handler handler) +      : connect_op_base(socket, &connect_op::do_complete), +        handler_(handler)      { -      io_service_.post(bind_handler(this->handler_, ec)); +    } + +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) +    { +      // Take ownership of the handler object. +      connect_op* o(static_cast<connect_op*>(base)); +      typedef handler_alloc_traits<Handler, connect_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); + +      // Make the upcall if required. +      if (owner) +      { +        // 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::binder1<Handler, boost::system::error_code> +          handler(o->handler_, o->ec_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      }    private: -    socket_type socket_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_; +    Handler handler_;    };    // Start an asynchronous connect. @@ -1767,59 +1638,103 @@ public:    void async_connect(implementation_type& impl,        const endpoint_type& peer_endpoint, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor)); -      return; -    } +    // Allocate and construct an operation to wrap the handler. +    typedef connect_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.socket_, handler); + +    start_connect_op(impl, ptr.get(), peer_endpoint); +    ptr.release(); +  } -    // Make socket non-blocking. -    if (!(impl.flags_ & implementation_type::internal_non_blocking)) +private: +  // Start the asynchronous read or write operation. +  void start_op(implementation_type& impl, int op_type, +      reactor_op* op, bool non_blocking, bool noop) +  { +    if (!noop)      { -      if (!(impl.flags_ & implementation_type::non_blocking)) +      if (is_open(impl))        { -        ioctl_arg_type non_blocking = 1; -        boost::system::error_code ec; -        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) +        if (!non_blocking || is_non_blocking(impl) +            || set_non_blocking(impl, op->ec_))          { -          this->get_io_service().post(bind_handler(handler, ec)); +          reactor_.start_op(op_type, impl.socket_, +              impl.reactor_data_, op, non_blocking);            return;          }        } -      impl.flags_ |= implementation_type::internal_non_blocking; +      else +        op->ec_ = boost::asio::error::bad_descriptor;      } -    // Start the connect operation. The socket is already marked as non-blocking -    // so the connection will take place asynchronously. -    boost::system::error_code ec; -    if (socket_ops::connect(impl.socket_, peer_endpoint.data(), -          peer_endpoint.size(), ec) == 0) +    io_service_impl_.post_immediate_completion(op); +  } + +  // Start the asynchronous accept operation. +  void start_accept_op(implementation_type& impl, +      reactor_op* op, bool peer_is_open) +  { +    if (!peer_is_open) +      start_op(impl, reactor::read_op, op, true, false); +    else      { -      // The connect operation has finished successfully so we need to post the -      // handler immediately. -      this->get_io_service().post(bind_handler(handler, -            boost::system::error_code())); +      op->ec_ = boost::asio::error::already_open; +      io_service_impl_.post_immediate_completion(op);      } -    else if (ec == boost::asio::error::in_progress -        || ec == boost::asio::error::would_block) +  } + +  // Start the asynchronous connect operation. +  void start_connect_op(implementation_type& impl, +      reactor_op* op, const endpoint_type& peer_endpoint) +  { +    if (is_open(impl))      { -      // The connection is happening in the background, and we need to wait -      // until the socket becomes writeable. -      reactor_.start_connect_op(impl.socket_, impl.reactor_data_, -          connect_operation<Handler>(impl.socket_, -            this->get_io_service(), handler)); +      if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_)) +      { +        if (socket_ops::connect(impl.socket_, peer_endpoint.data(), +              peer_endpoint.size(), op->ec_) != 0) +        { +          if (op->ec_ == boost::asio::error::in_progress +              || op->ec_ == boost::asio::error::would_block) +          { +            op->ec_ = boost::system::error_code(); +            reactor_.start_op(reactor::connect_op, +                impl.socket_, impl.reactor_data_, op, false); +            return; +          } +        } +      }      }      else -    { -      // The connect operation has failed, so post the handler immediately. -      this->get_io_service().post(bind_handler(handler, ec)); -    } +      op->ec_ = boost::asio::error::bad_descriptor; + +    io_service_impl_.post_immediate_completion(op);    } -private: +  // Determine whether the socket has been set non-blocking. +  bool is_non_blocking(implementation_type& impl) const +  { +    return (impl.flags_ & implementation_type::non_blocking); +  } + +  // Set the internal non-blocking flag. +  bool set_non_blocking(implementation_type& impl, +      boost::system::error_code& ec) +  { +    ioctl_arg_type non_blocking = 1; +    if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) +      return false; +    impl.flags_ |= implementation_type::internal_non_blocking; +    return true; +  } + +  // The io_service implementation used to post completions. +  io_service_impl& io_service_impl_; +    // The selector that performs event demultiplexing for the service. -  Reactor& reactor_; +  reactor& reactor_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/reactor.hpp b/3rdParty/Boost/src/boost/asio/detail/reactor.hpp new file mode 100644 index 0000000..43e432b --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/reactor.hpp @@ -0,0 +1,34 @@ +// +// reactor.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/reactor_fwd.hpp> + +#if defined(BOOST_ASIO_HAS_EPOLL) +# include <boost/asio/detail/epoll_reactor.hpp> +#elif defined(BOOST_ASIO_HAS_KQUEUE) +# include <boost/asio/detail/kqueue_reactor.hpp> +#elif defined(BOOST_ASIO_HAS_DEV_POLL) +# include <boost/asio/detail/dev_poll_reactor.hpp> +#else +# include <boost/asio/detail/select_reactor.hpp> +#endif + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_REACTOR_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/reactor_fwd.hpp b/3rdParty/Boost/src/boost/asio/detail/reactor_fwd.hpp new file mode 100644 index 0000000..9ff05eb --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/reactor_fwd.hpp @@ -0,0 +1,48 @@ +// +// reactor_fwd.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTOR_FWD_HPP +#define BOOST_ASIO_DETAIL_REACTOR_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/dev_poll_reactor_fwd.hpp> +#include <boost/asio/detail/epoll_reactor_fwd.hpp> +#include <boost/asio/detail/kqueue_reactor_fwd.hpp> +#include <boost/asio/detail/select_reactor_fwd.hpp> +#include <boost/asio/detail/win_iocp_io_service_fwd.hpp> + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_HAS_IOCP) +typedef select_reactor<true> reactor; +#elif defined(BOOST_ASIO_HAS_EPOLL) +typedef epoll_reactor reactor; +#elif defined(BOOST_ASIO_HAS_KQUEUE) +typedef kqueue_reactor reactor; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) +typedef dev_poll_reactor reactor; +#else +typedef select_reactor<false> reactor; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_REACTOR_FWD_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/reactor_op.hpp b/3rdParty/Boost/src/boost/asio/detail/reactor_op.hpp new file mode 100644 index 0000000..40647ec --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/reactor_op.hpp @@ -0,0 +1,62 @@ +// +// reactor_op.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_HPP +#define BOOST_ASIO_DETAIL_REACTOR_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/operation.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class reactor_op +  : public operation +{ +public: +  // The error code to be passed to the completion handler. +  boost::system::error_code ec_; + +  // The number of bytes transferred, to be passed to the completion handler. +  std::size_t bytes_transferred_; + +  // Perform the operation. Returns true if it is finished. +  bool perform() +  { +    return perform_func_(this); +  } + +protected: +  typedef bool (*perform_func_type)(reactor_op*); + +  reactor_op(perform_func_type perform_func, func_type complete_func) +    : operation(complete_func), +      bytes_transferred_(0), +      perform_func_(perform_func) +  { +  } + +private: +  perform_func_type perform_func_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_REACTOR_OP_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp b/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp index 46f0c10..0dd5654 100644 --- a/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp @@ -17,14 +17,11 @@  #include <boost/asio/detail/push_options.hpp> -#include <boost/asio/detail/push_options.hpp> -#include <memory> -#include <boost/asio/detail/pop_options.hpp> -  #include <boost/asio/error.hpp> -#include <boost/asio/detail/handler_alloc_helpers.hpp>  #include <boost/asio/detail/hash_map.hpp>  #include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/reactor_op.hpp>  namespace boost {  namespace asio { @@ -37,39 +34,21 @@ class reactor_op_queue  public:    // Constructor.    reactor_op_queue() -    : operations_(), -      cancelled_operations_(0), -      complete_operations_(0) +    : operations_()    {    }    // Add a new operation to the queue. Returns true if this is the only    // operation for the given descriptor, in which case the reactor's event    // demultiplexing function call may need to be interrupted and restarted. -  template <typename Operation> -  bool enqueue_operation(Descriptor descriptor, Operation operation) +  bool enqueue_operation(Descriptor descriptor, reactor_op* op)    { -    // Allocate and construct an object to wrap the handler. -    typedef handler_alloc_traits<Operation, op<Operation> > alloc_traits; -    raw_handler_ptr<alloc_traits> raw_ptr(operation); -    handler_ptr<alloc_traits> ptr(raw_ptr, descriptor, operation); - -    typedef typename operation_map::iterator iterator; -    typedef typename operation_map::value_type value_type; +    typedef typename operations_map::iterator iterator; +    typedef typename operations_map::value_type value_type;      std::pair<iterator, bool> entry = -      operations_.insert(value_type(descriptor, ptr.get())); -    if (entry.second) -    { -      ptr.release(); -      return true; -    } - -    op_base* current_op = entry.first->second; -    while (current_op->next_) -      current_op = current_op->next_; -    current_op->next_ = ptr.release(); - -    return false; +      operations_.insert(value_type(descriptor, operations())); +    entry.first->second.op_queue_.push(op); +    return entry.second;    }    // Cancel all operations associated with the descriptor. Any operations @@ -77,16 +56,19 @@ public:    // next time perform_cancellations is called. Returns true if any operations    // were cancelled, in which case the reactor's event demultiplexing function    // may need to be interrupted and restarted. -  bool cancel_operations(Descriptor descriptor) +  bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops, +      const boost::system::error_code& ec = +        boost::asio::error::operation_aborted)    { -    typename operation_map::iterator i = operations_.find(descriptor); +    typename operations_map::iterator i = operations_.find(descriptor);      if (i != operations_.end())      { -      op_base* last_op = i->second; -      while (last_op->next_) -        last_op = last_op->next_; -      last_op->next_ = cancelled_operations_; -      cancelled_operations_ = i->second; +      while (reactor_op* op = i->second.op_queue_.front()) +      { +        op->ec_ = ec; +        i->second.op_queue_.pop(); +        ops.push(op); +      }        operations_.erase(i);        return true;      } @@ -106,79 +88,37 @@ public:      return operations_.find(descriptor) != operations_.end();    } -  // Perform the first operation corresponding to the descriptor. Returns true -  // if there are more operations queued for the descriptor. -  bool perform_operation(Descriptor descriptor, -      const boost::system::error_code& result) +  // Perform the operations corresponding to the descriptor. Returns true if +  // there are still unfinished operations queued for the descriptor. +  bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)    { -    typename operation_map::iterator i = operations_.find(descriptor); +    typename operations_map::iterator i = operations_.find(descriptor);      if (i != operations_.end())      { -      op_base* this_op = i->second; -      i->second = this_op->next_; -      this_op->next_ = complete_operations_; -      complete_operations_ = this_op; -      bool done = this_op->perform(result); -      if (done) +      while (reactor_op* op = i->second.op_queue_.front())        { -        // Operation has finished. -        if (i->second) +        if (op->perform())          { -          return true; +          i->second.op_queue_.pop(); +          ops.push(op);          }          else          { -          operations_.erase(i); -          return false; -        } -      } -      else -      { -        // Operation wants to be called again. Leave it at the front of the -        // queue for this descriptor, and remove from the completed list. -        complete_operations_ = this_op->next_; -        this_op->next_ = i->second; -        i->second = this_op; -        return true; -      } -    } -    return false; -  } - -  // Perform all operations corresponding to the descriptor. -  void perform_all_operations(Descriptor descriptor, -      const boost::system::error_code& result) -  { -    typename operation_map::iterator i = operations_.find(descriptor); -    if (i != operations_.end()) -    { -      while (i->second) -      { -        op_base* this_op = i->second; -        i->second = this_op->next_; -        this_op->next_ = complete_operations_; -        complete_operations_ = this_op; -        bool done = this_op->perform(result); -        if (!done) -        { -          // Operation has not finished yet, so leave at front of queue, and -          // remove from the completed list. -          complete_operations_ = this_op->next_; -          this_op->next_ = i->second; -          i->second = this_op; -          return; +          return true;          }        }        operations_.erase(i);      } +    return false;    }    // Fill a descriptor set with the descriptors corresponding to each active -  // operation. +  // operation. The op_queue is used only when descriptors fail to be added to +  // the descriptor set.    template <typename Descriptor_Set> -  void get_descriptors(Descriptor_Set& descriptors) +  void get_descriptors(Descriptor_Set& descriptors, op_queue<operation>& ops)    { -    typename operation_map::iterator i = operations_.begin(); +    typename operations_map::iterator i = operations_.begin();      while (i != operations_.end())      {        Descriptor descriptor = i->first; @@ -186,7 +126,7 @@ public:        if (!descriptors.set(descriptor))        {          boost::system::error_code ec(error::fd_set_failure); -        perform_all_operations(descriptor, ec); +        cancel_operations(descriptor, ops, ec);        }      }    } @@ -194,257 +134,62 @@ public:    // Perform the operations corresponding to the ready file descriptors    // contained in the given descriptor set.    template <typename Descriptor_Set> -  void perform_operations_for_descriptors(const Descriptor_Set& descriptors, -      const boost::system::error_code& result) +  void perform_operations_for_descriptors( +      const Descriptor_Set& descriptors, op_queue<operation>& ops)    { -    typename operation_map::iterator i = operations_.begin(); +    typename operations_map::iterator i = operations_.begin();      while (i != operations_.end())      { -      typename operation_map::iterator op_iter = i++; +      typename operations_map::iterator op_iter = i++;        if (descriptors.is_set(op_iter->first))        { -        op_base* this_op = op_iter->second; -        op_iter->second = this_op->next_; -        this_op->next_ = complete_operations_; -        complete_operations_ = this_op; -        bool done = this_op->perform(result); -        if (done) -        { -          if (!op_iter->second) -            operations_.erase(op_iter); -        } -        else +        while (reactor_op* op = op_iter->second.op_queue_.front())          { -          // Operation has not finished yet, so leave at front of queue, and -          // remove from the completed list. -          complete_operations_ = this_op->next_; -          this_op->next_ = op_iter->second; -          op_iter->second = this_op; +          if (op->perform()) +          { +            op_iter->second.op_queue_.pop(); +            ops.push(op); +          } +          else +          { +            break; +          }          } -      } -    } -  } - -  // Perform any pending cancels for operations. -  void perform_cancellations() -  { -    while (cancelled_operations_) -    { -      op_base* this_op = cancelled_operations_; -      cancelled_operations_ = this_op->next_; -      this_op->next_ = complete_operations_; -      complete_operations_ = this_op; -      this_op->perform(boost::asio::error::operation_aborted); -    } -  } -  // Complete all operations that are waiting to be completed. -  void complete_operations() -  { -    while (complete_operations_) -    { -      op_base* next_op = complete_operations_->next_; -      complete_operations_->next_ = 0; -      complete_operations_->complete(); -      complete_operations_ = next_op; +        if (op_iter->second.op_queue_.empty()) +          operations_.erase(op_iter); +      }      }    } -  // Destroy all operations owned by the queue. -  void destroy_operations() +  // Get all operations owned by the queue. +  void get_all_operations(op_queue<operation>& ops)    { -    while (cancelled_operations_) -    { -      op_base* next_op = cancelled_operations_->next_; -      cancelled_operations_->next_ = 0; -      cancelled_operations_->destroy(); -      cancelled_operations_ = next_op; -    } - -    while (complete_operations_) -    { -      op_base* next_op = complete_operations_->next_; -      complete_operations_->next_ = 0; -      complete_operations_->destroy(); -      complete_operations_ = next_op; -    } - -    typename operation_map::iterator i = operations_.begin(); +    typename operations_map::iterator i = operations_.begin();      while (i != operations_.end())      { -      typename operation_map::iterator op_iter = i++; -      op_base* curr_op = op_iter->second; +      typename operations_map::iterator op_iter = i++; +      ops.push(op_iter->second.op_queue_);        operations_.erase(op_iter); -      while (curr_op) -      { -        op_base* next_op = curr_op->next_; -        curr_op->next_ = 0; -        curr_op->destroy(); -        curr_op = next_op; -      }      }    }  private: -  // Base class for reactor operations. A function pointer is used instead of -  // virtual functions to avoid the associated overhead. -  class op_base -  { -  public: -    // Get the descriptor associated with the operation. -    Descriptor descriptor() const -    { -      return descriptor_; -    } - -    // Perform the operation. -    bool perform(const boost::system::error_code& result) -    { -      result_ = result; -      return perform_func_(this, result_, bytes_transferred_); -    } - -    // Destroy the operation and post the handler. -    void complete() -    { -      complete_func_(this, result_, bytes_transferred_); -    } - -    // Destroy the operation. -    void destroy() -    { -      destroy_func_(this); -    } - -  protected: -    typedef bool (*perform_func_type)(op_base*, -        boost::system::error_code&, std::size_t&); -    typedef void (*complete_func_type)(op_base*, -        const boost::system::error_code&, std::size_t); -    typedef void (*destroy_func_type)(op_base*); - -    // Construct an operation for the given descriptor. -    op_base(perform_func_type perform_func, complete_func_type complete_func, -        destroy_func_type destroy_func, Descriptor descriptor) -      : perform_func_(perform_func), -        complete_func_(complete_func), -        destroy_func_(destroy_func), -        descriptor_(descriptor), -        result_(), -        bytes_transferred_(0), -        next_(0) -    { -    } - -    // Prevent deletion through this type. -    ~op_base() -    { -    } - -  private: -    friend class reactor_op_queue<Descriptor>; - -    // The function to be called to perform the operation. -    perform_func_type perform_func_; - -    // The function to be called to delete the operation and post the handler. -    complete_func_type complete_func_; - -    // The function to be called to delete the operation. -    destroy_func_type destroy_func_; - -    // The descriptor associated with the operation. -    Descriptor descriptor_; - -    // The result of the operation. -    boost::system::error_code result_; - -    // The number of bytes transferred in the operation. -    std::size_t bytes_transferred_; - -    // The next operation for the same file descriptor. -    op_base* next_; -  }; - -  // Adaptor class template for operations. -  template <typename Operation> -  class op -    : public op_base +  struct operations    { -  public: -    // Constructor. -    op(Descriptor descriptor, Operation operation) -      : op_base(&op<Operation>::do_perform, &op<Operation>::do_complete, -          &op<Operation>::do_destroy, descriptor), -        operation_(operation) -    { -    } - -    // Perform the operation. -    static bool do_perform(op_base* base, -        boost::system::error_code& result, std::size_t& bytes_transferred) -    { -      return static_cast<op<Operation>*>(base)->operation_.perform( -          result, bytes_transferred); -    } - -    // Destroy the operation and post the handler. -    static void do_complete(op_base* base, -        const boost::system::error_code& result, std::size_t bytes_transferred) -    { -      // Take ownership of the operation object. -      typedef op<Operation> this_type; -      this_type* this_op(static_cast<this_type*>(base)); -      typedef handler_alloc_traits<Operation, this_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(this_op->operation_, this_op); - -      // Make a copy of the error_code and the operation so that the memory can -      // be deallocated before the upcall is made. -      boost::system::error_code ec(result); -      Operation operation(this_op->operation_); - -      // Free the memory associated with the operation. -      ptr.reset(); - -      // Make the upcall. -      operation.complete(ec, bytes_transferred); -    } - -    // Destroy the operation. -    static void do_destroy(op_base* base) -    { -      // Take ownership of the operation object. -      typedef op<Operation> this_type; -      this_type* this_op(static_cast<this_type*>(base)); -      typedef handler_alloc_traits<Operation, this_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(this_op->operation_, this_op); - -      // A sub-object of the operation may be the true owner of the memory -      // associated with the operation. Consequently, a local copy of the -      // operation is required to ensure that any owning sub-object remains -      // valid until after we have deallocated the memory here. -      Operation operation(this_op->operation_); -      (void)operation; - -      // Free the memory associated with the operation. -      ptr.reset(); -    } +    operations() {} +    operations(const operations&) {} +    void operator=(const operations&) {} -  private: -    Operation operation_; +    // The operations waiting on the desccriptor. +    op_queue<reactor_op> op_queue_;    };    // The type for a map of operations. -  typedef hash_map<Descriptor, op_base*> operation_map; +  typedef hash_map<Descriptor, operations> operations_map;    // The operations that are currently executing asynchronously. -  operation_map operations_; - -  // The list of operations that have been cancelled. -  op_base* cancelled_operations_; - -  // The list of operations waiting to be completed. -  op_base* complete_operations_; +  operations_map operations_;  };  } // namespace detail 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_; diff --git a/3rdParty/Boost/src/boost/asio/detail/select_reactor.hpp b/3rdParty/Boost/src/boost/asio/detail/select_reactor.hpp index ba8b5d3..91030e9 100644 --- a/3rdParty/Boost/src/boost/asio/detail/select_reactor.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/select_reactor.hpp @@ -22,9 +22,6 @@  #include <boost/asio/detail/push_options.hpp>  #include <cstddef>  #include <boost/config.hpp> -#include <boost/date_time/posix_time/posix_time_types.hpp> -#include <boost/shared_ptr.hpp> -#include <vector>  #include <boost/asio/detail/pop_options.hpp>  #include <boost/asio/io_service.hpp> @@ -32,6 +29,8 @@  #include <boost/asio/detail/fd_set_adapter.hpp>  #include <boost/asio/detail/mutex.hpp>  #include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/reactor_op.hpp>  #include <boost/asio/detail/reactor_op_queue.hpp>  #include <boost/asio/detail/select_interrupter.hpp>  #include <boost/asio/detail/select_reactor_fwd.hpp> @@ -39,9 +38,11 @@  #include <boost/asio/detail/signal_blocker.hpp>  #include <boost/asio/detail/socket_ops.hpp>  #include <boost/asio/detail/socket_types.hpp> -#include <boost/asio/detail/task_io_service.hpp>  #include <boost/asio/detail/thread.hpp> -#include <boost/asio/detail/timer_queue.hpp> +#include <boost/asio/detail/timer_op.hpp> +#include <boost/asio/detail/timer_queue_base.hpp> +#include <boost/asio/detail/timer_queue_fwd.hpp> +#include <boost/asio/detail/timer_queue_set.hpp>  namespace boost {  namespace asio { @@ -52,6 +53,14 @@ class select_reactor    : public boost::asio::detail::service_base<select_reactor<Own_Thread> >  {  public: +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +  enum { read_op = 0, write_op = 1, except_op = 2, +    max_select_ops = 3, connect_op = 3, max_ops = 4 }; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +  enum { read_op = 0, write_op = 1, except_op = 2, +    max_select_ops = 3, connect_op = 1, max_ops = 3 }; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +    // Per-descriptor data.    struct per_descriptor_data    { @@ -61,13 +70,9 @@ public:    select_reactor(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<          select_reactor<Own_Thread> >(io_service), +      io_service_(use_service<io_service_impl>(io_service)),        mutex_(), -      select_in_progress_(false),        interrupter_(), -      read_op_queue_(), -      write_op_queue_(), -      except_op_queue_(), -      pending_cancellations_(),        stop_thread_(false),        thread_(0),        shutdown_(false) @@ -94,31 +99,29 @@ public:      stop_thread_ = true;      lock.unlock(); -    if (thread_) +    if (Own_Thread)      { -      interrupter_.interrupt(); -      thread_->join(); -      delete thread_; -      thread_ = 0; +      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(); +    op_queue<operation> ops; -    for (std::size_t i = 0; i < timer_queues_.size(); ++i) -      timer_queues_[i]->destroy_timers(); -    timer_queues_.clear(); +    for (int i = 0; i < max_ops; ++i) +      op_queue_[i].get_all_operations(ops); + +    timer_queues_.get_all_timers(ops);    }    // Initialise the task, but only if the reactor is not in its own thread.    void init_task()    { -    if (!Own_Thread) -    { -      typedef task_io_service<select_reactor<Own_Thread> > task_io_service_type; -      use_service<task_io_service_type>(this->get_io_service()).init_task(); -    } +    io_service_.init_task();    }    // Register a socket with the reactor. Returns 0 on success, system error @@ -128,111 +131,17 @@ public:      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, per_descriptor_data&, -      Handler handler, bool /*allow_speculative_read*/ = true) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    if (!shutdown_) -      if (read_op_queue_.enqueue_operation(descriptor, handler)) -        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, per_descriptor_data&, -      Handler handler, bool /*allow_speculative_write*/ = true) +  // Start a new operation. The reactor operation will be performed when the +  // given descriptor is flagged as ready, or an error has occurred. +  void start_op(int op_type, socket_type descriptor, +      per_descriptor_data&, reactor_op* op, bool)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_);      if (!shutdown_) -      if (write_op_queue_.enqueue_operation(descriptor, handler)) -        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, -      per_descriptor_data&, Handler handler) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    if (!shutdown_) -      if (except_op_queue_.enqueue_operation(descriptor, handler)) -        interrupter_.interrupt(); -  } - -  // Wrapper for connect handlers to enable the handler object to be placed -  // in both the write and the except operation queues, but ensure that only -  // one of the handlers is called. -  template <typename Handler> -  class connect_handler_wrapper -  { -  public: -    connect_handler_wrapper(socket_type descriptor, -        boost::shared_ptr<bool> completed, -        select_reactor<Own_Thread>& reactor, Handler handler) -      : descriptor_(descriptor), -        completed_(completed), -        reactor_(reactor), -        handler_(handler)      { -    } - -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) -    { -      // Check whether one of the handlers has already been called. If it has, -      // then we don't want to do anything in this handler. -      if (*completed_) -      { -        completed_.reset(); // Indicate that this handler should not complete. -        return true; -      } - -      // Cancel the other reactor operation for the connection. -      *completed_ = true; -      reactor_.enqueue_cancel_ops_unlocked(descriptor_); - -      // Call the contained handler. -      return handler_.perform(ec, bytes_transferred); -    } - -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      if (completed_.get()) -        handler_.complete(ec, bytes_transferred); -    } - -  private: -    socket_type descriptor_; -    boost::shared_ptr<bool> completed_; -    select_reactor<Own_Thread>& reactor_; -    Handler handler_; -  }; - -  // 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. The handler will be called -  // only once. -  template <typename Handler> -  void start_connect_op(socket_type descriptor, -      per_descriptor_data&, Handler handler) -  { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    if (!shutdown_) -    { -      boost::shared_ptr<bool> completed(new bool(false)); -      connect_handler_wrapper<Handler> wrapped_handler( -          descriptor, completed, *this, handler); -      bool interrupt = write_op_queue_.enqueue_operation( -          descriptor, wrapped_handler); -      interrupt = except_op_queue_.enqueue_operation( -          descriptor, wrapped_handler) || interrupt; -      if (interrupt) +      bool first = op_queue_[op_type].enqueue_operation(descriptor, op); +      io_service_.work_started(); +      if (first)          interrupter_.interrupt();      }    } @@ -243,17 +152,7 @@ public:    void cancel_ops(socket_type descriptor, per_descriptor_data&)    {      boost::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 -  // select_reactor's mutex, and so should only be used when the reactor lock is -  // already held. -  void enqueue_cancel_ops_unlocked(socket_type descriptor) -  { -    pending_cancellations_.push_back(descriptor); +    cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);    }    // Cancel any operations that are running against the descriptor and remove @@ -261,7 +160,7 @@ public:    void close_descriptor(socket_type descriptor, per_descriptor_data&)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    cancel_ops_unlocked(descriptor); +    cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);    }    // Add a new timer queue to the reactor. @@ -269,7 +168,7 @@ public:    void add_timer_queue(timer_queue<Time_Traits>& timer_queue)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    timer_queues_.push_back(&timer_queue); +    timer_queues_.insert(&timer_queue);    }    // Remove a timer queue from the reactor. @@ -277,252 +176,186 @@ public:    void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)    {      boost::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; -      } -    } +    timer_queues_.erase(&timer_queue);    } -  // 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> +  // Schedule a new operation in the given timer queue to expire at the +  // specified absolute time. +  template <typename Time_Traits>    void schedule_timer(timer_queue<Time_Traits>& timer_queue, -      const typename Time_Traits::time_type& time, Handler handler, void* token) +      const typename Time_Traits::time_type& time, timer_op* op, void* token)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_);      if (!shutdown_) -      if (timer_queue.enqueue_timer(time, handler, token)) +    { +      bool earliest = timer_queue.enqueue_timer(time, op, token); +      io_service_.work_started(); +      if (earliest)          interrupter_.interrupt(); +    }    } -  // Cancel the timer associated with the given token. Returns the number of -  // handlers that have been posted or dispatched. +  // Cancel the timer operations associated with the given token. Returns the +  // number of operations that have been posted or dispatched.    template <typename Time_Traits>    std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    std::size_t n = timer_queue.cancel_timer(token); -    if (n > 0) -      interrupter_.interrupt(); +    op_queue<operation> ops; +    std::size_t n = timer_queue.cancel_timer(token, ops); +    lock.unlock(); +    io_service_.post_deferred_completions(ops);      return n;    } -private: -  friend class task_io_service<select_reactor<Own_Thread> >; -    // Run select once until interrupted or events are ready to be dispatched. -  void run(bool block) +  void run(bool block, op_queue<operation>& ops)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    // Dispatch any operation cancellations that were made while the select -    // loop was not running. -    read_op_queue_.perform_cancellations(); -    write_op_queue_.perform_cancellations(); -    except_op_queue_.perform_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_) +    if (Own_Thread) +      if (stop_thread_) +        return; + +    // Set up the descriptor sets. +    fd_set_adapter fds[max_select_ops]; +    fds[read_op].set(interrupter_.read_descriptor()); +    socket_type max_fd = 0; +    bool have_work_to_do = !timer_queues_.all_empty(); +    for (int i = 0; i < max_select_ops; ++i)      { -      complete_operations_and_timers(lock); -      return; +      have_work_to_do = have_work_to_do || !op_queue_[i].empty(); +      op_queue_[i].get_descriptors(fds[i], ops); +      if (fds[i].max_descriptor() > max_fd) +        max_fd = fds[i].max_descriptor();      } +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +    // Connection operations on Windows use both except and write fd_sets. +    have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty(); +    op_queue_[connect_op].get_descriptors(fds[write_op], ops); +    if (fds[write_op].max_descriptor() > max_fd) +      max_fd = fds[write_op].max_descriptor(); +    op_queue_[connect_op].get_descriptors(fds[except_op], ops); +    if (fds[except_op].max_descriptor() > max_fd) +      max_fd = fds[except_op].max_descriptor(); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +      // 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()) -    { -      complete_operations_and_timers(lock); +    if (!block && !have_work_to_do)        return; -    } -    // Set up the descriptor sets. -    fd_set_adapter read_fds; -    read_fds.set(interrupter_.read_descriptor()); -    read_op_queue_.get_descriptors(read_fds); -    fd_set_adapter write_fds; -    write_op_queue_.get_descriptors(write_fds); -    fd_set_adapter except_fds; -    except_op_queue_.get_descriptors(except_fds); -    socket_type max_fd = read_fds.max_descriptor(); -    if (write_fds.max_descriptor() > max_fd) -      max_fd = write_fds.max_descriptor(); -    if (except_fds.max_descriptor() > max_fd) -      max_fd = except_fds.max_descriptor(); - -    // Block on the select call without holding the lock so that new -    // operations can be started while the call is executing. +    // Determine how long to block while waiting for events.      timeval tv_buf = { 0, 0 };      timeval* tv = block ? get_timeout(tv_buf) : &tv_buf; -    select_in_progress_ = true; +      lock.unlock(); + +    // Block on the select call until descriptors become ready.      boost::system::error_code ec;      int retval = socket_ops::select(static_cast<int>(max_fd + 1), -        read_fds, write_fds, except_fds, tv, ec); -    lock.lock(); -    select_in_progress_ = false; +        fds[read_op], fds[write_op], fds[except_op], tv, ec);      // Reset the interrupter. -    if (retval > 0 && read_fds.is_set(interrupter_.read_descriptor())) +    if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))        interrupter_.reset(); +    lock.lock(); +      // Dispatch all ready operations.      if (retval > 0)      { +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +      // Connection operations on Windows use both except and write fd_sets. +      op_queue_[connect_op].perform_operations_for_descriptors( +          fds[except_op], ops); +      op_queue_[connect_op].perform_operations_for_descriptors( +          fds[write_op], ops); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +        // Exception operations must be processed first to ensure that any        // out-of-band data is read before normal data. -      except_op_queue_.perform_operations_for_descriptors( -          except_fds, boost::system::error_code()); -      read_op_queue_.perform_operations_for_descriptors( -          read_fds, boost::system::error_code()); -      write_op_queue_.perform_operations_for_descriptors( -          write_fds, boost::system::error_code()); -      except_op_queue_.perform_cancellations(); -      read_op_queue_.perform_cancellations(); -      write_op_queue_.perform_cancellations(); +      for (int i = max_select_ops - 1; i >= 0; --i) +        op_queue_[i].perform_operations_for_descriptors(fds[i], ops);      } -    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(); +    timer_queues_.get_ready_timers(ops); +  } -    complete_operations_and_timers(lock); +  // Interrupt the select loop. +  void interrupt() +  { +    interrupter_.interrupt();    } +private:    // Run the select loop in the thread.    void run_thread()    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_); -    while (!stop_thread_) +    if (Own_Thread)      { -      lock.unlock(); -      run(true); -      lock.lock(); +      boost::asio::detail::mutex::scoped_lock lock(mutex_); +      while (!stop_thread_) +      { +        lock.unlock(); +        op_queue<operation> ops; +        run(true, ops); +        io_service_.post_deferred_completions(ops); +        lock.lock(); +      }      }    }    // Entry point for the select loop thread.    static void call_run_thread(select_reactor* reactor)    { -    reactor->run_thread(); -  } - -  // Interrupt the select loop. -  void interrupt() -  { -    interrupter_.interrupt(); -  } - -  // 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; +    if (Own_Thread) +    { +      reactor->run_thread(); +    }    }    // Get the timeout value for the select call.    timeval* get_timeout(timeval& tv)    { -    if (all_timer_queues_are_empty()) -      return 0; -      // 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()) -    { -      tv.tv_sec = minimum_wait_duration.total_seconds(); -      tv.tv_usec = minimum_wait_duration.total_microseconds() % 1000000; -    } -    else -    { -      tv.tv_sec = 0; -      tv.tv_usec = 0; -    } - +    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); +    tv.tv_sec = usec / 1000000; +    tv.tv_usec = usec % 1000000;      return &tv;    } -  // 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 select_reactor's mutex. -  void cancel_ops_unlocked(socket_type descriptor) +  // Cancel all operations associated with the given descriptor. This function +  // does not acquire the select_reactor's mutex. +  void cancel_ops_unlocked(socket_type descriptor, +      const boost::system::error_code& ec)    { -    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) +    bool need_interrupt = false; +    op_queue<operation> ops; +    for (int i = 0; i < max_ops; ++i) +      need_interrupt = op_queue_[i].cancel_operations( +          descriptor, ops, ec) || need_interrupt; +    io_service_.post_deferred_completions(ops); +    if (need_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 complete_operations_and_timers( -      boost::asio::detail::mutex::scoped_lock& lock) -  { -    timer_queues_for_cleanup_ = timer_queues_; -    lock.unlock(); -    read_op_queue_.complete_operations(); -    write_op_queue_.complete_operations(); -    except_op_queue_.complete_operations(); -    for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) -      timer_queues_for_cleanup_[i]->complete_timers(); -  } +  // The io_service implementation used to post completions. +  io_service_impl& io_service_;    // Mutex to protect access to internal data.    boost::asio::detail::mutex mutex_; -  // Whether the select loop is currently running or not. -  bool select_in_progress_; -    // The interrupter is used to break a blocking select call.    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 exception operations. -  reactor_op_queue<socket_type> except_op_queue_; +  // The queues of read, write and except operations. +  reactor_op_queue<socket_type> op_queue_[max_ops];    // 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_; +  timer_queue_set timer_queues_;    // Does the reactor loop thread need to stop.    bool stop_thread_; diff --git a/3rdParty/Boost/src/boost/asio/detail/service_registry.hpp b/3rdParty/Boost/src/boost/asio/detail/service_registry.hpp index b648939..e640ec8 100644 --- a/3rdParty/Boost/src/boost/asio/detail/service_registry.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/service_registry.hpp @@ -18,7 +18,6 @@  #include <boost/asio/detail/push_options.hpp>  #include <boost/asio/detail/push_options.hpp> -#include <memory>  #include <typeinfo>  #include <boost/asio/detail/pop_options.hpp> @@ -80,7 +79,7 @@ public:      while (first_service_)      {        boost::asio::io_service::service* next_service = first_service_->next_; -      delete first_service_; +      destroy(first_service_);        first_service_ = next_service;      }    } @@ -91,14 +90,105 @@ public:    template <typename Service>    Service& use_service()    { +    boost::asio::io_service::service::key key; +    init_key(key, Service::id); +    factory_type factory = &service_registry::create<Service>; +    return *static_cast<Service*>(do_use_service(key, factory)); +  } + +  // Add a service object. Returns false on error, in which case ownership of +  // the object is retained by the caller. +  template <typename Service> +  bool add_service(Service* new_service) +  { +    boost::asio::io_service::service::key key; +    init_key(key, Service::id); +    return do_add_service(key, new_service); +  } + +  // Check whether a service object of the specified type already exists. +  template <typename Service> +  bool has_service() const +  { +    boost::asio::io_service::service::key key; +    init_key(key, Service::id); +    return do_has_service(key); +  } + +private: +  // Initialise a service's key based on its id. +  void init_key(boost::asio::io_service::service::key& key, +      const boost::asio::io_service::id& id) +  { +    key.type_info_ = 0; +    key.id_ = &id; +  } + +#if !defined(BOOST_ASIO_NO_TYPEID) +  // Initialise a service's key based on its id. +  template <typename Service> +  void init_key(boost::asio::io_service::service::key& key, +      const boost::asio::detail::service_id<Service>& /*id*/) +  { +    key.type_info_ = &typeid(typeid_wrapper<Service>); +    key.id_ = 0; +  } +#endif // !defined(BOOST_ASIO_NO_TYPEID) + +  // Check if a service matches the given id. +  static bool keys_match( +      const boost::asio::io_service::service::key& key1, +      const boost::asio::io_service::service::key& key2) +  { +    if (key1.id_ && key2.id_) +      if (key1.id_ == key2.id_) +        return true; +    if (key1.type_info_ && key2.type_info_) +      if (*key1.type_info_ == *key2.type_info_) +        return true; +    return false; +  } + +  // The type of a factory function used for creating a service instance. +  typedef boost::asio::io_service::service* +    (*factory_type)(boost::asio::io_service&); + +  // Factory function for creating a service instance. +  template <typename Service> +  static boost::asio::io_service::service* create( +      boost::asio::io_service& owner) +  { +    return new Service(owner); +  } + +  // Destroy a service instance. +  static void destroy(boost::asio::io_service::service* service) +  { +    delete service; +  } + +  // Helper class to manage service pointers. +  struct auto_service_ptr +  { +    boost::asio::io_service::service* ptr_; +    ~auto_service_ptr() { destroy(ptr_); } +  }; + +  // Get the service object corresponding to the specified service key. Will +  // create a new service object automatically if no such object already +  // exists. Ownership of the service object is not transferred to the caller. +  boost::asio::io_service::service* do_use_service( +      const boost::asio::io_service::service::key& key, +      factory_type factory) +  {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    // First see if there is an existing service object for the given type. +    // First see if there is an existing service object with the given key.      boost::asio::io_service::service* service = first_service_;      while (service)      { -      if (service_id_matches(*service, Service::id)) -        return *static_cast<Service*>(service); +      if (keys_match(service->key_, key)) +        return service;        service = service->next_;      } @@ -106,9 +196,8 @@ public:      // at this time to allow for nested calls into this function from the new      // service's constructor.      lock.unlock(); -    std::auto_ptr<Service> new_service(new Service(owner_)); -    init_service_id(*new_service, Service::id); -    Service& new_service_ref = *new_service; +    auto_service_ptr new_service = { factory(owner_) }; +    new_service.ptr_->key_ = key;      lock.lock();      // Check that nobody else created another service object of the same type @@ -116,52 +205,52 @@ public:      service = first_service_;      while (service)      { -      if (service_id_matches(*service, Service::id)) -        return *static_cast<Service*>(service); +      if (keys_match(service->key_, key)) +        return service;        service = service->next_;      }      // Service was successfully initialised, pass ownership to registry. -    new_service->next_ = first_service_; -    first_service_ = new_service.release(); - -    return new_service_ref; +    new_service.ptr_->next_ = first_service_; +    first_service_ = new_service.ptr_; +    new_service.ptr_ = 0; +    return first_service_;    }    // Add a service object. Returns false on error, in which case ownership of    // the object is retained by the caller. -  template <typename Service> -  bool add_service(Service* new_service) +  bool do_add_service( +      const boost::asio::io_service::service::key& key, +      boost::asio::io_service::service* new_service)    {      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    // Check if there is an existing service object for the given type. +    // Check if there is an existing service object with the given key.      boost::asio::io_service::service* service = first_service_;      while (service)      { -      if (service_id_matches(*service, Service::id)) +      if (keys_match(service->key_, key))          return false;        service = service->next_;      }      // Take ownership of the service object. -    init_service_id(*new_service, Service::id); +    new_service->key_ = key;      new_service->next_ = first_service_;      first_service_ = new_service;      return true;    } -  // Check whether a service object of the specified type already exists. -  template <typename Service> -  bool has_service() const +  // Check whether a service object with the specified key already exists. +  bool do_has_service(const boost::asio::io_service::service::key& key) const    {      boost::asio::detail::mutex::scoped_lock lock(mutex_);      boost::asio::io_service::service* service = first_service_;      while (service)      { -      if (service_id_matches(*service, Service::id)) +      if (keys_match(service->key_, key))          return true;        service = service->next_;      } @@ -169,46 +258,6 @@ public:      return false;    } -private: -  // Set a service's id. -  void init_service_id(boost::asio::io_service::service& service, -      const boost::asio::io_service::id& id) -  { -    service.type_info_ = 0; -    service.id_ = &id; -  } - -#if !defined(BOOST_ASIO_NO_TYPEID) -  // Set a service's id. -  template <typename Service> -  void init_service_id(boost::asio::io_service::service& service, -      const boost::asio::detail::service_id<Service>& /*id*/) -  { -    service.type_info_ = &typeid(typeid_wrapper<Service>); -    service.id_ = 0; -  } -#endif // !defined(BOOST_ASIO_NO_TYPEID) - -  // Check if a service matches the given id. -  static bool service_id_matches( -      const boost::asio::io_service::service& service, -      const boost::asio::io_service::id& id) -  { -    return service.id_ == &id; -  } - -#if !defined(BOOST_ASIO_NO_TYPEID) -  // Check if a service matches the given id. -  template <typename Service> -  static bool service_id_matches( -      const boost::asio::io_service::service& service, -      const boost::asio::detail::service_id<Service>& /*id*/) -  { -    return service.type_info_ != 0 -      && *service.type_info_ == typeid(typeid_wrapper<Service>); -  } -#endif // !defined(BOOST_ASIO_NO_TYPEID) -    // Mutex to protect access to internal data.    mutable boost::asio::detail::mutex mutex_; diff --git a/3rdParty/Boost/src/boost/asio/detail/signal_blocker.hpp b/3rdParty/Boost/src/boost/asio/detail/signal_blocker.hpp index db11fe4..0197e04 100644 --- a/3rdParty/Boost/src/boost/asio/detail/signal_blocker.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/signal_blocker.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  # include <boost/asio/detail/null_signal_blocker.hpp>  #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)  # include <boost/asio/detail/win_signal_blocker.hpp> @@ -35,7 +35,7 @@ namespace boost {  namespace asio {  namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  typedef null_signal_blocker signal_blocker;  #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)  typedef win_signal_blocker signal_blocker; diff --git a/3rdParty/Boost/src/boost/asio/detail/socket_types.hpp b/3rdParty/Boost/src/boost/asio/detail/socket_types.hpp index 7395ee4..1009164 100644 --- a/3rdParty/Boost/src/boost/asio/detail/socket_types.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/socket_types.hpp @@ -68,13 +68,15 @@  #   define WIN32_LEAN_AND_MEAN  #  endif // !defined(WIN32_LEAN_AND_MEAN)  # endif // !defined(BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN) +# if !defined(BOOST_ASIO_NO_NOMINMAX) +#  if !defined(NOMINMAX) +#   define NOMINMAX 1 +#  endif // !defined(NOMINMAX) +# endif // !defined(BOOST_ASIO_NO_NOMINMAX)  # if defined(__CYGWIN__)  #  if !defined(__USE_W32_SOCKETS)  #   error You must add -D__USE_W32_SOCKETS to your compiler options.  #  endif // !defined(__USE_W32_SOCKETS) -#  if !defined(NOMINMAX) -#   define NOMINMAX 1 -#  endif // !defined(NOMINMAX)  # endif // defined(__CYGWIN__)  # include <winsock2.h>  # include <ws2tcpip.h> diff --git a/3rdParty/Boost/src/boost/asio/detail/solaris_fenced_block.hpp b/3rdParty/Boost/src/boost/asio/detail/solaris_fenced_block.hpp new file mode 100644 index 0000000..be9803e --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/solaris_fenced_block.hpp @@ -0,0 +1,59 @@ +// +// solaris_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/push_options.hpp> +#include <boost/config.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#if defined(__sun) + +#include <boost/asio/detail/push_options.hpp> +#include <atomic.h> +#include <boost/asio/detail/pop_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class solaris_fenced_block +  : private noncopyable +{ +public: +  // Constructor. +  solaris_fenced_block() +  { +    membar_consumer(); +  } + +  // Destructor. +  ~solaris_fenced_block() +  { +    membar_producer(); +  } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(__sun) + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/strand_service.hpp b/3rdParty/Boost/src/boost/asio/detail/strand_service.hpp index b228cec..d6b45b1 100644 --- a/3rdParty/Boost/src/boost/asio/detail/strand_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/strand_service.hpp @@ -18,19 +18,19 @@  #include <boost/asio/detail/push_options.hpp>  #include <boost/asio/detail/push_options.hpp> -#include <boost/aligned_storage.hpp> -#include <boost/assert.hpp>  #include <boost/functional/hash.hpp>  #include <boost/scoped_ptr.hpp>  #include <boost/asio/detail/pop_options.hpp>  #include <boost/asio/io_service.hpp> -#include <boost/asio/detail/bind_handler.hpp>  #include <boost/asio/detail/call_stack.hpp> +#include <boost/asio/detail/completion_handler.hpp> +#include <boost/asio/detail/fenced_block.hpp>  #include <boost/asio/detail/handler_alloc_helpers.hpp>  #include <boost/asio/detail/handler_invoke_helpers.hpp>  #include <boost/asio/detail/mutex.hpp> -#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/operation.hpp>  #include <boost/asio/detail/service_base.hpp>  namespace boost { @@ -41,252 +41,45 @@ namespace detail {  class strand_service    : public boost::asio::detail::service_base<strand_service>  { +private: +  struct on_do_complete_exit; +  struct on_dispatch_exit; +  public: -  class handler_base; -  class invoke_current_handler; -  class post_next_waiter_on_exit;    // The underlying implementation of a strand.    class strand_impl +    : public operation    {    public:      strand_impl() -      : current_handler_(0), -        first_waiter_(0), -        last_waiter_(0) +      : operation(&strand_service::do_complete), +        count_(0)      {      }    private:      // Only this service will have access to the internal values.      friend class strand_service; -    friend class post_next_waiter_on_exit; -    friend class invoke_current_handler; +    friend struct on_do_complete_exit; +    friend struct on_dispatch_exit;      // Mutex to protect access to internal data.      boost::asio::detail::mutex mutex_; -    // The handler that is ready to execute. If this pointer is non-null then it -    // indicates that a handler holds the lock. -    handler_base* current_handler_; - -    // The start of the list of waiting handlers for the strand. -    handler_base* first_waiter_; -     -    // The end of the list of waiting handlers for the strand. -    handler_base* last_waiter_; - -    // Storage for posted handlers. -    typedef boost::aligned_storage<128> handler_storage_type; -#if defined(__BORLANDC__) -    boost::aligned_storage<128> handler_storage_; -#else -    handler_storage_type handler_storage_; -#endif -  }; - -  friend class strand_impl; - -  typedef strand_impl* implementation_type; - -  // Base class for all handler types. -  class handler_base -  { -  public: -    typedef void (*invoke_func_type)(handler_base*, -        strand_service&, implementation_type&); -    typedef void (*destroy_func_type)(handler_base*); - -    handler_base(invoke_func_type invoke_func, destroy_func_type destroy_func) -      : next_(0), -        invoke_func_(invoke_func), -        destroy_func_(destroy_func) -    { -    } - -    void invoke(strand_service& service_impl, implementation_type& impl) -    { -      invoke_func_(this, service_impl, impl); -    } - -    void destroy() -    { -      destroy_func_(this); -    } - -  protected: -    ~handler_base() -    { -    } - -  private: -    friend class strand_service; -    friend class strand_impl; -    friend class post_next_waiter_on_exit; -    handler_base* next_; -    invoke_func_type invoke_func_; -    destroy_func_type destroy_func_; -  }; - -  // Helper class to allow handlers to be dispatched. -  class invoke_current_handler -  { -  public: -    invoke_current_handler(strand_service& service_impl, -        const implementation_type& impl) -      : service_impl_(service_impl), -        impl_(impl) -    { -    } - -    void operator()() -    { -      impl_->current_handler_->invoke(service_impl_, impl_); -    } - -    friend void* asio_handler_allocate(std::size_t size, -        invoke_current_handler* this_handler) -    { -      return this_handler->do_handler_allocate(size); -    } - -    friend void asio_handler_deallocate(void*, std::size_t, -        invoke_current_handler*) -    { -    } - -    void* do_handler_allocate(std::size_t size) -    { -#if defined(__BORLANDC__) -      BOOST_ASSERT(size <= boost::aligned_storage<128>::size); -#else -      BOOST_ASSERT(size <= strand_impl::handler_storage_type::size); -#endif -      (void)size; -      return impl_->handler_storage_.address(); -    } - -    // The asio_handler_invoke hook is not defined here since the default one -    // provides the correct behaviour, and including it here breaks MSVC 7.1 -    // in some situations. - -  private: -    strand_service& service_impl_; -    implementation_type impl_; -  }; - -  // Helper class to automatically enqueue next waiter on block exit. -  class post_next_waiter_on_exit -  { -  public: -    post_next_waiter_on_exit(strand_service& service_impl, -        implementation_type& impl) -      : service_impl_(service_impl), -        impl_(impl), -        cancelled_(false) -    { -    } - -    ~post_next_waiter_on_exit() -    { -      if (!cancelled_) -      { -        boost::asio::detail::mutex::scoped_lock lock(impl_->mutex_); -        impl_->current_handler_ = impl_->first_waiter_; -        if (impl_->current_handler_) -        { -          impl_->first_waiter_ = impl_->first_waiter_->next_; -          if (impl_->first_waiter_ == 0) -            impl_->last_waiter_ = 0; -          lock.unlock(); -          service_impl_.get_io_service().post( -              invoke_current_handler(service_impl_, impl_)); -        } -      } -    } - -    void cancel() -    { -      cancelled_ = true; -    } +    // The count of handlers in the strand, including the upcall (if any). +    std::size_t count_; -  private: -    strand_service& service_impl_; -    implementation_type& impl_; -    bool cancelled_; +    // The handlers waiting on the strand. +    op_queue<operation> queue_;    }; -  // Class template for a waiter. -  template <typename Handler> -  class handler_wrapper -    : public handler_base -  { -  public: -    handler_wrapper(Handler handler) -      : handler_base(&handler_wrapper<Handler>::do_invoke, -          &handler_wrapper<Handler>::do_destroy), -        handler_(handler) -    { -    } - -    static void do_invoke(handler_base* base, -        strand_service& service_impl, implementation_type& impl) -    { -      // 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); - -      post_next_waiter_on_exit p1(service_impl, impl); - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(h->handler_); - -      // A handler object must still be valid when the next waiter is posted -      // since destroying the last handler might cause the strand object to be -      // destroyed. Therefore we create a second post_next_waiter_on_exit object -      // that will be destroyed before the handler object. -      p1.cancel(); -      post_next_waiter_on_exit p2(service_impl, impl); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Indicate that this strand is executing on the current thread. -      call_stack<strand_impl>::context ctx(impl); - -      // Make the upcall. -      boost_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); - -      // 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. -      Handler handler(h->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset(); -    } - -  private: -    Handler handler_; -  }; +  typedef strand_impl* implementation_type;    // Construct a new strand service for the specified io_service.    explicit strand_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<strand_service>(io_service), +      io_service_(boost::asio::use_service<io_service_impl>(io_service)),        mutex_(),        salt_(0)    { @@ -295,37 +88,13 @@ public:    // Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { -    // Construct a list of all handlers to be destroyed. +    op_queue<operation> ops; +      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    handler_base* first_handler = 0; +      for (std::size_t i = 0; i < num_implementations; ++i) -    {        if (strand_impl* impl = implementations_[i].get()) -      { -        if (impl->current_handler_) -        { -          impl->current_handler_->next_ = first_handler; -          first_handler = impl->current_handler_; -          impl->current_handler_ = 0; -        } -        if (impl->first_waiter_) -        { -          impl->last_waiter_->next_ = first_handler; -          first_handler = impl->first_waiter_; -          impl->first_waiter_ = 0; -          impl->last_waiter_ = 0; -        } -      } -    } - -    // Destroy all handlers without holding the lock. -    lock.unlock(); -    while (first_handler) -    { -      handler_base* next = first_handler->next_; -      first_handler->destroy(); -      first_handler = next; -    } +        ops.push(impl->queue_);    }    // Construct a new strand implementation. @@ -352,45 +121,54 @@ public:    template <typename Handler>    void dispatch(implementation_type& impl, Handler handler)    { +    // If we are already in the strand then the handler can run immediately.      if (call_stack<strand_impl>::contains(impl))      { +      boost::asio::detail::fenced_block b;        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      return;      } -    else + +    // Allocate and construct an object to wrap the handler. +    typedef completion_handler<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); + +    // If we are running inside the io_service, and no other handler is queued +    // or running, then the handler can run immediately. +    bool can_dispatch = call_stack<io_service_impl>::contains(&io_service_); +    impl->mutex_.lock(); +    bool first = (++impl->count_ == 1); +    if (can_dispatch && first)      { -      // 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(handler); -      handler_ptr<alloc_traits> ptr(raw_ptr, handler); - -      boost::asio::detail::mutex::scoped_lock lock(impl->mutex_); - -      if (impl->current_handler_ == 0) -      { -        // This handler now has the lock, so can be dispatched immediately. -        impl->current_handler_ = ptr.release(); -        lock.unlock(); -        this->get_io_service().dispatch(invoke_current_handler(*this, impl)); -      } -      else -      { -        // Another handler already holds the lock, so this handler must join -        // the list of waiters. The handler will be posted automatically when -        // its turn comes. -        if (impl->last_waiter_) -        { -          impl->last_waiter_->next_ = ptr.get(); -          impl->last_waiter_ = impl->last_waiter_->next_; -        } -        else -        { -          impl->first_waiter_ = ptr.get(); -          impl->last_waiter_ = ptr.get(); -        } -        ptr.release(); -      } +      // Immediate invocation is allowed. +      impl->mutex_.unlock(); + +      // Memory must be releaesed before any upcall is made. +      ptr.reset(); + +      // Indicate that this strand is executing on the current thread. +      call_stack<strand_impl>::context ctx(impl); + +      // Ensure the next handler, if any, is scheduled on block exit. +      on_dispatch_exit on_exit = { &io_service_, impl }; +      (void)on_exit; + +      boost::asio::detail::fenced_block b; +      boost_asio_handler_invoke_helpers::invoke(handler, handler); +      return;      } + +    // Immediate invocation is not allowed, so enqueue for later. +    impl->queue_.push(ptr.get()); +    impl->mutex_.unlock(); +    ptr.release(); + +    // The first handler to be enqueued is responsible for scheduling the +    // strand. +    if (first) +      io_service_.post_immediate_completion(impl);    }    // Request the io_service to invoke the given handler and return immediately. @@ -398,40 +176,85 @@ public:    void post(implementation_type& impl, Handler handler)    {      // Allocate and construct an object to wrap the handler. -    typedef handler_wrapper<Handler> value_type; +    typedef completion_handler<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); -    boost::asio::detail::mutex::scoped_lock lock(impl->mutex_); +    // Add the handler to the queue. +    impl->mutex_.lock(); +    bool first = (++impl->count_ == 1); +    impl->queue_.push(ptr.get()); +    impl->mutex_.unlock(); +    ptr.release(); + +    // The first handler to be enqueue is responsible for scheduling the strand. +    if (first) +      io_service_.post_immediate_completion(impl); +  } + +private: +  static void do_complete(io_service_impl* owner, operation* base, +      boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) +  { +    if (owner) +    { +      strand_impl* impl = static_cast<strand_impl*>(base); + +      // Get the next handler to be executed. +      impl->mutex_.lock(); +      operation* o = impl->queue_.front(); +      impl->queue_.pop(); +      impl->mutex_.unlock(); + +      // Indicate that this strand is executing on the current thread. +      call_stack<strand_impl>::context ctx(impl); + +      // Ensure the next handler, if any, is scheduled on block exit. +      on_do_complete_exit on_exit = { owner, impl }; +      (void)on_exit; + +      o->complete(*owner); +    } +  } + +  // Helper class to re-post the strand on exit. +  struct on_do_complete_exit +  { +    io_service_impl* owner_; +    strand_impl* impl_; -    if (impl->current_handler_ == 0) +    ~on_do_complete_exit()      { -      // This handler now has the lock, so can be dispatched immediately. -      impl->current_handler_ = ptr.release(); -      lock.unlock(); -      this->get_io_service().post(invoke_current_handler(*this, impl)); +      impl_->mutex_.lock(); +      bool more_handlers = (--impl_->count_ > 0); +      impl_->mutex_.unlock(); + +      if (more_handlers) +        owner_->post_immediate_completion(impl_);      } -    else +  }; + +  // Helper class to re-post the strand on exit. +  struct on_dispatch_exit +  { +    io_service_impl* io_service_; +    strand_impl* impl_; + +    ~on_dispatch_exit()      { -      // Another handler already holds the lock, so this handler must join the -      // list of waiters. The handler will be posted automatically when its turn -      // comes. -      if (impl->last_waiter_) -      { -        impl->last_waiter_->next_ = ptr.get(); -        impl->last_waiter_ = impl->last_waiter_->next_; -      } -      else -      { -        impl->first_waiter_ = ptr.get(); -        impl->last_waiter_ = ptr.get(); -      } -      ptr.release(); +      impl_->mutex_.lock(); +      bool more_handlers = (--impl_->count_ > 0); +      impl_->mutex_.unlock(); + +      if (more_handlers) +        io_service_->post_immediate_completion(impl_);      } -  } +  }; + +  // The io_service implementation used to post completions. +  io_service_impl& io_service_; -private:    // Mutex to protect access to the array of implementations.    boost::asio::detail::mutex mutex_; diff --git a/3rdParty/Boost/src/boost/asio/detail/task_io_service.hpp b/3rdParty/Boost/src/boost/asio/detail/task_io_service.hpp index ddfea72..f6de370 100644 --- a/3rdParty/Boost/src/boost/asio/detail/task_io_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/task_io_service.hpp @@ -15,21 +15,25 @@  # pragma once  #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#if defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) -#include <boost/asio/detail/task_io_service_2lock.hpp> -#else // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) -  #include <boost/asio/detail/push_options.hpp>  #include <boost/asio/io_service.hpp>  #include <boost/asio/detail/call_stack.hpp> +#include <boost/asio/detail/completion_handler.hpp>  #include <boost/asio/detail/event.hpp> +#include <boost/asio/detail/fenced_block.hpp>  #include <boost/asio/detail/handler_alloc_helpers.hpp>  #include <boost/asio/detail/handler_invoke_helpers.hpp> -#include <boost/asio/detail/handler_queue.hpp>  #include <boost/asio/detail/mutex.hpp> +#include <boost/asio/detail/op_queue.hpp>  #include <boost/asio/detail/service_base.hpp>  #include <boost/asio/detail/task_io_service_fwd.hpp> +#include <boost/asio/detail/task_io_service_operation.hpp> + +#include <boost/asio/detail/push_options.hpp> +#include <boost/detail/atomic_count.hpp> +#include <boost/system/error_code.hpp> +#include <boost/asio/detail/pop_options.hpp>  namespace boost {  namespace asio { @@ -40,6 +44,8 @@ class task_io_service    : public boost::asio::detail::service_base<task_io_service<Task> >  {  public: +  typedef task_io_service_operation<Task> operation; +    // Constructor.    task_io_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<task_io_service<Task> >(io_service), @@ -65,12 +71,12 @@ public:      lock.unlock();      // Destroy handler objects. -    while (!handler_queue_.empty()) +    while (!op_queue_.empty())      { -      handler_queue::handler* h = handler_queue_.front(); -      handler_queue_.pop(); -      if (h != &task_handler_) -        h->destroy(); +      operation* o = op_queue_.front(); +      op_queue_.pop(); +      if (o != &task_operation_) +        o->destroy();      }      // Reset to initial state. @@ -84,14 +90,21 @@ public:      if (!shutdown_ && !task_)      {        task_ = &use_service<Task>(this->get_io_service()); -      handler_queue_.push(&task_handler_); -      interrupt_one_idle_thread(lock); +      op_queue_.push(&task_operation_); +      wake_one_thread_and_unlock(lock);      }    }    // Run the event loop until interrupted or no more work.    size_t run(boost::system::error_code& ec)    { +    ec = boost::system::error_code(); +    if (outstanding_work_ == 0) +    { +      stop(); +      return 0; +    } +      typename call_stack<task_io_service>::context ctx(this);      idle_thread_info this_idle_thread; @@ -100,7 +113,7 @@ public:      boost::asio::detail::mutex::scoped_lock lock(mutex_);      size_t n = 0; -    while (do_one(lock, &this_idle_thread, ec)) +    for (; do_one(lock, &this_idle_thread); lock.lock())        if (n != (std::numeric_limits<size_t>::max)())          ++n;      return n; @@ -109,6 +122,13 @@ public:    // Run until interrupted or one operation is performed.    size_t run_one(boost::system::error_code& ec)    { +    ec = boost::system::error_code(); +    if (outstanding_work_ == 0) +    { +      stop(); +      return 0; +    } +      typename call_stack<task_io_service>::context ctx(this);      idle_thread_info this_idle_thread; @@ -116,18 +136,25 @@ public:      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    return do_one(lock, &this_idle_thread, ec); +    return do_one(lock, &this_idle_thread);    }    // Poll for operations without blocking.    size_t poll(boost::system::error_code& ec)    { +    if (outstanding_work_ == 0) +    { +      stop(); +      ec = boost::system::error_code(); +      return 0; +    } +      typename call_stack<task_io_service>::context ctx(this);      boost::asio::detail::mutex::scoped_lock lock(mutex_);      size_t n = 0; -    while (do_one(lock, 0, ec)) +    for (; do_one(lock, 0); lock.lock())        if (n != (std::numeric_limits<size_t>::max)())          ++n;      return n; @@ -136,11 +163,18 @@ public:    // Poll for one operation without blocking.    size_t poll_one(boost::system::error_code& ec)    { +    ec = boost::system::error_code(); +    if (outstanding_work_ == 0) +    { +      stop(); +      return 0; +    } +      typename call_stack<task_io_service>::context ctx(this);      boost::asio::detail::mutex::scoped_lock lock(mutex_); -    return do_one(lock, 0, ec); +    return do_one(lock, 0);    }    // Interrupt the event processing loop. @@ -160,16 +194,14 @@ public:    // Notify that some work has started.    void work_started()    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_);      ++outstanding_work_;    }    // Notify that some work has finished.    void work_finished()    { -    boost::asio::detail::mutex::scoped_lock lock(mutex_);      if (--outstanding_work_ == 0) -      stop_all_threads(lock); +      stop();    }    // Request invocation of the given handler. @@ -177,7 +209,10 @@ public:    void dispatch(Handler handler)    {      if (call_stack<task_io_service>::contains(this)) +    { +      boost::asio::detail::fenced_block b;        boost_asio_handler_invoke_helpers::invoke(handler, handler); +    }      else        post(handler);    } @@ -187,29 +222,41 @@ public:    void post(Handler handler)    {      // Allocate and construct an operation to wrap the handler. -    handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); - -    boost::asio::detail::mutex::scoped_lock lock(mutex_); - -    // If the service has been shut down we silently discard the handler. -    if (shutdown_) -      return; +    typedef completion_handler<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); -    // Add the handler to the end of the queue. -    handler_queue_.push(ptr.get()); +    post_immediate_completion(ptr.get());      ptr.release(); +  } -    // An undelivered handler is treated as unfinished work. -    ++outstanding_work_; +  // Request invocation of the given operation and return immediately. Assumes +  // that work_started() has not yet been called for the operation. +  void post_immediate_completion(operation* op) +  { +    work_started(); +    post_deferred_completion(op); +  } + +  // Request invocation of the given operation and return immediately. Assumes +  // that work_started() was previously called for the operation. +  void post_deferred_completion(operation* op) +  { +    boost::asio::detail::mutex::scoped_lock lock(mutex_); +    op_queue_.push(op); +    wake_one_thread_and_unlock(lock); +  } -    // Wake up a thread to execute the handler. -    if (!interrupt_one_idle_thread(lock)) +  // Request invocation of the given operations and return immediately. Assumes +  // that work_started() was previously called for each operation. +  void post_deferred_completions(op_queue<operation>& ops) +  { +    if (!ops.empty())      { -      if (!task_interrupted_ && task_) -      { -        task_interrupted_ = true; -        task_->interrupt(); -      } +      boost::asio::detail::mutex::scoped_lock lock(mutex_); +      op_queue_.push(ops); +      wake_one_thread_and_unlock(lock);      }    } @@ -217,57 +264,58 @@ private:    struct idle_thread_info;    size_t do_one(boost::asio::detail::mutex::scoped_lock& lock, -      idle_thread_info* this_idle_thread, boost::system::error_code& ec) +      idle_thread_info* this_idle_thread)    { -    if (outstanding_work_ == 0 && !stopped_) -    { -      stop_all_threads(lock); -      ec = boost::system::error_code(); -      return 0; -    } -      bool polling = !this_idle_thread;      bool task_has_run = false;      while (!stopped_)      { -      if (!handler_queue_.empty()) +      if (!op_queue_.empty())        {          // Prepare to execute first handler from queue. -        handler_queue::handler* h = handler_queue_.front(); -        handler_queue_.pop(); +        operation* o = op_queue_.front(); +        op_queue_.pop(); +        bool more_handlers = (!op_queue_.empty()); -        if (h == &task_handler_) +        if (o == &task_operation_)          { -          bool more_handlers = (!handler_queue_.empty());            task_interrupted_ = more_handlers || polling;            // 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 = boost::system::error_code(); +            op_queue_.push(&task_operation_);              return 0;            }            task_has_run = true; -          lock.unlock(); -          task_cleanup c(lock, *this); +          if (!more_handlers || !wake_one_idle_thread_and_unlock(lock)) +            lock.unlock(); -          // Run the task. May throw an exception. Only block if the handler -          // queue is empty and we have an idle_thread_info object, otherwise -          // we want to return as soon as possible. -          task_->run(!more_handlers && !polling); +          op_queue<operation> completed_ops; +          task_cleanup c = { this, &lock, &completed_ops }; +          (void)c; + +          // Run the task. May throw an exception. Only block if the operation +          // queue is empty and we're not polling, otherwise we want to return +          // as soon as possible. +          task_->run(!more_handlers && !polling, completed_ops);          }          else          { -          lock.unlock(); -          handler_cleanup c(lock, *this); +          if (more_handlers) +            wake_one_thread_and_unlock(lock); +          else +            lock.unlock(); + +          // Ensure the count of outstanding work is decremented on block exit. +          work_finished_on_block_exit on_exit = { this }; +          (void)on_exit; -          // Invoke the handler. May throw an exception. -          h->invoke(); // invoke() deletes the handler object +          // Complete the operation. May throw an exception. +          o->complete(*this); // deletes the operation object -          ec = boost::system::error_code();            return 1;          }        } @@ -281,12 +329,10 @@ private:        }        else        { -        ec = boost::system::error_code();          return 0;        }      } -    ec = boost::system::error_code();      return 0;    } @@ -295,7 +341,15 @@ private:        boost::asio::detail::mutex::scoped_lock& lock)    {      stopped_ = true; -    interrupt_all_idle_threads(lock); + +    while (first_idle_thread_) +    { +      idle_thread_info* idle_thread = first_idle_thread_; +      first_idle_thread_ = idle_thread->next; +      idle_thread->next = 0; +      idle_thread->wakeup_event.signal(lock); +    } +      if (!task_interrupted_ && task_)      {        task_interrupted_ = true; @@ -303,9 +357,10 @@ private:      }    } -  // Interrupt a single idle thread. Returns true if a thread was interrupted, -  // false if no running thread could be found to interrupt. -  bool interrupt_one_idle_thread( +  // Wakes a single idle thread and unlocks the mutex. Returns true if an idle +  // thread was found. If there is no idle thread, returns false and leaves the +  // mutex locked. +  bool wake_one_idle_thread_and_unlock(        boost::asio::detail::mutex::scoped_lock& lock)    {      if (first_idle_thread_) @@ -313,74 +368,56 @@ private:        idle_thread_info* idle_thread = first_idle_thread_;        first_idle_thread_ = idle_thread->next;        idle_thread->next = 0; -      idle_thread->wakeup_event.signal(lock); +      idle_thread->wakeup_event.signal_and_unlock(lock);        return true;      }      return false;    } -  // Interrupt all idle threads. -  void interrupt_all_idle_threads( +  // Wake a single idle thread, or the task, and always unlock the mutex. +  void wake_one_thread_and_unlock(        boost::asio::detail::mutex::scoped_lock& lock)    { -    while (first_idle_thread_) +    if (!wake_one_idle_thread_and_unlock(lock))      { -      idle_thread_info* idle_thread = first_idle_thread_; -      first_idle_thread_ = idle_thread->next; -      idle_thread->next = 0; -      idle_thread->wakeup_event.signal(lock); +      if (!task_interrupted_ && task_) +      { +        task_interrupted_ = true; +        task_->interrupt(); +      } +      lock.unlock();      }    }    // Helper class to perform task-related operations on block exit. -  class task_cleanup; -  friend class task_cleanup; -  class task_cleanup +  struct task_cleanup; +  friend struct task_cleanup; +  struct task_cleanup    { -  public: -    task_cleanup(boost::asio::detail::mutex::scoped_lock& lock, -        task_io_service& task_io_svc) -      : lock_(lock), -        task_io_service_(task_io_svc) -    { -    } -      ~task_cleanup()      { -      // Reinsert the task at the end of the handler queue. -      lock_.lock(); -      task_io_service_.task_interrupted_ = true; -      task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); +      // Enqueue the completed operations and reinsert the task at the end of +      // the operation queue. +      lock_->lock(); +      task_io_service_->task_interrupted_ = true; +      task_io_service_->op_queue_.push(*ops_); +      task_io_service_->op_queue_.push(&task_io_service_->task_operation_);      } -  private: -    boost::asio::detail::mutex::scoped_lock& lock_; -    task_io_service& task_io_service_; +    task_io_service* task_io_service_; +    boost::asio::detail::mutex::scoped_lock* lock_; +    op_queue<operation>* ops_;    }; -  // Helper class to perform handler-related operations on block exit. -  class handler_cleanup; -  friend class handler_cleanup; -  class handler_cleanup +  // Helper class to call work_finished() on block exit. +  struct work_finished_on_block_exit    { -  public: -    handler_cleanup(boost::asio::detail::mutex::scoped_lock& lock, -        task_io_service& task_io_svc) -      : lock_(lock), -        task_io_service_(task_io_svc) -    { -    } - -    ~handler_cleanup() +    ~work_finished_on_block_exit()      { -      lock_.lock(); -      if (--task_io_service_.outstanding_work_ == 0) -        task_io_service_.stop_all_threads(lock_); +      task_io_service_->work_finished();      } -  private: -    boost::asio::detail::mutex::scoped_lock& lock_; -    task_io_service& task_io_service_; +    task_io_service* task_io_service_;    };    // Mutex to protect access to internal data. @@ -389,25 +426,20 @@ private:    // The task to be run by this service.    Task* task_; -  // Handler object to represent the position of the task in the queue. -  class task_handler -    : public handler_queue::handler +  // Operation object to represent the position of the task in the queue. +  struct task_operation : public operation    { -  public: -    task_handler() -      : handler_queue::handler(0, 0) -    { -    } -  } task_handler_; +    task_operation() : operation(0) {} +  } task_operation_;    // Whether the task has been interrupted.    bool task_interrupted_;    // The count of unfinished work. -  int outstanding_work_; +  boost::detail::atomic_count outstanding_work_;    // The queue of handlers that are ready to be delivered. -  handler_queue handler_queue_; +  op_queue<operation> op_queue_;    // Flag to indicate that the dispatcher has been stopped.    bool stopped_; @@ -422,7 +454,7 @@ private:      idle_thread_info* next;    }; -  // The number of threads that are currently idle. +  // The threads that are currently idle.    idle_thread_info* first_idle_thread_;  }; @@ -430,9 +462,6 @@ private:  } // namespace asio  } // namespace boost -#include <boost/system/error_code.hpp>  #include <boost/asio/detail/pop_options.hpp> -#endif // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) -  #endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/task_io_service_2lock.hpp b/3rdParty/Boost/src/boost/asio/detail/task_io_service_2lock.hpp deleted file mode 100644 index 71bceef..0000000 --- a/3rdParty/Boost/src/boost/asio/detail/task_io_service_2lock.hpp +++ /dev/null @@ -1,475 +0,0 @@ -// -// task_io_service_2lock.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP -#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/push_options.hpp> - -#include <boost/asio/io_service.hpp> -#include <boost/asio/detail/call_stack.hpp> -#include <boost/asio/detail/event.hpp> -#include <boost/asio/detail/handler_alloc_helpers.hpp> -#include <boost/asio/detail/handler_invoke_helpers.hpp> -#include <boost/asio/detail/indirect_handler_queue.hpp> -#include <boost/asio/detail/mutex.hpp> -#include <boost/asio/detail/service_base.hpp> -#include <boost/asio/detail/task_io_service_fwd.hpp> - -#include <boost/asio/detail/push_options.hpp> -#include <boost/detail/atomic_count.hpp> -#include <boost/system/error_code.hpp> -#include <boost/asio/detail/pop_options.hpp> - -namespace boost { -namespace asio { -namespace detail { - -// An alternative task_io_service implementation based on a two-lock queue. - -template <typename Task> -class task_io_service -  : public boost::asio::detail::service_base<task_io_service<Task> > -{ -public: -  typedef indirect_handler_queue handler_queue; - -  // Constructor. -  task_io_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base<task_io_service<Task> >(io_service), -      front_mutex_(), -      back_mutex_(), -      task_(0), -      outstanding_work_(0), -      front_stopped_(false), -      back_stopped_(false), -      back_shutdown_(false), -      back_first_idle_thread_(0), -      back_task_thread_(0) -  { -  } - -  void init(size_t /*concurrency_hint*/) -  { -  } - -  // Destroy all user-defined handler objects owned by the service. -  void shutdown_service() -  { -    boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); -    back_shutdown_ = true; -    back_lock.unlock(); - -    // Destroy handler objects. -    while (handler_queue::handler* h = handler_queue_.pop()) -      if (h != &task_handler_) -        h->destroy(); - -    // Reset to initial state. -    task_ = 0; -  } - -  // Initialise the task, if required. -  void init_task() -  { -    boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); -    if (!back_shutdown_ && !task_) -    { -      task_ = &use_service<Task>(this->get_io_service()); -      handler_queue_.push(&task_handler_); -      interrupt_one_idle_thread(back_lock); -    } -  } - -  // Run the event loop until interrupted or no more work. -  size_t run(boost::system::error_code& ec) -  { -    if (outstanding_work_ == 0) -    { -      stop(); -      ec = boost::system::error_code(); -      return 0; -    } - -    typename call_stack<task_io_service>::context ctx(this); - -    idle_thread_info this_idle_thread; -    this_idle_thread.next = 0; - -    size_t n = 0; -    while (do_one(&this_idle_thread, ec)) -      if (n != (std::numeric_limits<size_t>::max)()) -        ++n; -    return n; -  } - -  // Run until interrupted or one operation is performed. -  size_t run_one(boost::system::error_code& ec) -  { -    if (outstanding_work_ == 0) -    { -      stop(); -      ec = boost::system::error_code(); -      return 0; -    } - -    typename call_stack<task_io_service>::context ctx(this); - -    idle_thread_info this_idle_thread; -    this_idle_thread.next = 0; - -    return do_one(&this_idle_thread, ec); -  } - -  // Poll for operations without blocking. -  size_t poll(boost::system::error_code& ec) -  { -    if (outstanding_work_ == 0) -    { -      stop(); -      ec = boost::system::error_code(); -      return 0; -    } - -    typename call_stack<task_io_service>::context ctx(this); - -    size_t n = 0; -    while (do_one(0, ec)) -      if (n != (std::numeric_limits<size_t>::max)()) -        ++n; -    return n; -  } - -  // Poll for one operation without blocking. -  size_t poll_one(boost::system::error_code& ec) -  { -    if (outstanding_work_ == 0) -    { -      stop(); -      ec = boost::system::error_code(); -      return 0; -    } - -    typename call_stack<task_io_service>::context ctx(this); - -    return do_one(0, ec); -  } - -  // Interrupt the event processing loop. -  void stop() -  { -    boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); -    front_stopped_ = true; -    front_lock.unlock(); - -    boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); -    back_stopped_ = true; -    interrupt_all_idle_threads(back_lock); -  } - -  // Reset in preparation for a subsequent run invocation. -  void reset() -  { -    boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); -    front_stopped_ = false; -    front_lock.unlock(); - -    boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); -    back_stopped_ = false; -  } - -  // Notify that some work has started. -  void work_started() -  { -    ++outstanding_work_; -  } - -  // Notify that some work has finished. -  void work_finished() -  { -    if (--outstanding_work_ == 0) -      stop(); -  } - -  // Request invocation of the given handler. -  template <typename Handler> -  void dispatch(Handler handler) -  { -    if (call_stack<task_io_service>::contains(this)) -      boost_asio_handler_invoke_helpers::invoke(handler, handler); -    else -      post(handler); -  } - -  // Request invocation of the given handler and return immediately. -  template <typename Handler> -  void post(Handler handler) -  { -    // Allocate and construct an operation to wrap the handler. -    handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); - -    boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); - -    // If the service has been shut down we silently discard the handler. -    if (back_shutdown_) -      return; - -    // Add the handler to the end of the queue. -    handler_queue_.push(ptr.get()); -    ptr.release(); - -    // An undelivered handler is treated as unfinished work. -    ++outstanding_work_; - -    // Wake up a thread to execute the handler. -    interrupt_one_idle_thread(back_lock); -  } - -private: -  struct idle_thread_info; - -  size_t do_one(idle_thread_info* this_idle_thread, -      boost::system::error_code& ec) -  { -    bool task_has_run = false; -    for (;;) -    { -      // The front lock must be held before we can pop items from the queue. -      boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); -      if (front_stopped_) -      { -        ec = boost::system::error_code(); -        return 0; -      } - -      if (handler_queue::handler* h = handler_queue_.pop()) -      { -        if (h == &task_handler_) -        { -          bool more_handlers = handler_queue_.poppable(); -          unsigned long front_version = handler_queue_.front_version(); -          front_lock.unlock(); - -          // The task is always added to the back of the queue when we exit -          // this block. -          task_cleanup c(*this); - -          // If we're polling and the task has already run then we're done. -          bool polling = !this_idle_thread; -          if (task_has_run && polling) -          { -            ec = boost::system::error_code(); -            return 0; -          } - -          // If we're considering going idle we need to check whether the queue -          // is still empty. If it is, add the thread to the list of idle -          // threads. -          if (!more_handlers && !polling) -          { -            boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); -            if (back_stopped_) -            { -              ec = boost::system::error_code(); -              return 0; -            } -            else if (front_version == handler_queue_.back_version()) -            { -              back_task_thread_ = this_idle_thread; -            } -            else -            { -              more_handlers = true; -            } -          } - -          // Run the task. May throw an exception. Only block if the handler -          // queue is empty and we're not polling, otherwise we want to return -          // as soon as possible. -          task_has_run = true; -          task_->run(!more_handlers && !polling); -        } -        else -        { -          front_lock.unlock(); -          handler_cleanup c(*this); - -          // Invoke the handler. May throw an exception. -          h->invoke(); // invoke() deletes the handler object - -          ec = boost::system::error_code(); -          return 1; -        } -      } -      else if (this_idle_thread) -      { -        unsigned long front_version = handler_queue_.front_version(); -        front_lock.unlock(); - -        // If we're considering going idle we need to check whether the queue -        // is still empty. If it is, add the thread to the list of idle -        // threads. -        boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); -        if (back_stopped_) -        { -          ec = boost::system::error_code(); -          return 0; -        } -        else if (front_version == handler_queue_.back_version()) -        { -          this_idle_thread->next = back_first_idle_thread_; -          back_first_idle_thread_ = this_idle_thread; -          this_idle_thread->wakeup_event.clear(back_lock); -          this_idle_thread->wakeup_event.wait(back_lock); -        } -      } -      else -      { -        ec = boost::system::error_code(); -        return 0; -      } -    } -  } - -  // Interrupt a single idle thread. -  void interrupt_one_idle_thread( -      boost::asio::detail::mutex::scoped_lock& back_lock) -  { -    if (back_first_idle_thread_) -    { -      idle_thread_info* idle_thread = back_first_idle_thread_; -      back_first_idle_thread_ = idle_thread->next; -      idle_thread->next = 0; -      idle_thread->wakeup_event.signal(back_lock); -    } -    else if (back_task_thread_ && task_) -    { -      back_task_thread_ = 0; -      task_->interrupt(); -    } -  } - -  // Interrupt all idle threads. -  void interrupt_all_idle_threads( -      boost::asio::detail::mutex::scoped_lock& back_lock) -  { -    while (back_first_idle_thread_) -    { -      idle_thread_info* idle_thread = back_first_idle_thread_; -      back_first_idle_thread_ = idle_thread->next; -      idle_thread->next = 0; -      idle_thread->wakeup_event.signal(back_lock); -    } - -    if (back_task_thread_ && task_) -    { -      back_task_thread_ = 0; -      task_->interrupt(); -    } -  } - -  // Helper class to perform task-related operations on block exit. -  class task_cleanup; -  friend class task_cleanup; -  class task_cleanup -  { -  public: -    task_cleanup(task_io_service& task_io_svc) -      : task_io_service_(task_io_svc) -    { -    } - -    ~task_cleanup() -    { -      // Reinsert the task at the end of the handler queue. -      boost::asio::detail::mutex::scoped_lock back_lock( -          task_io_service_.back_mutex_); -      task_io_service_.back_task_thread_ = 0; -      task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); -    } - -  private: -    task_io_service& task_io_service_; -  }; - -  // Helper class to perform handler-related operations on block exit. -  class handler_cleanup -  { -  public: -    handler_cleanup(task_io_service& task_io_svc) -      : task_io_service_(task_io_svc) -    { -    } - -    ~handler_cleanup() -    { -      task_io_service_.work_finished(); -    } - -  private: -    task_io_service& task_io_service_; -  }; - -  // Mutexes to protect access to internal data. -  boost::asio::detail::mutex front_mutex_; -  boost::asio::detail::mutex back_mutex_; - -  // The task to be run by this service. -  Task* task_; - -  // Handler object to represent the position of the task in the queue. -  class task_handler -    : public handler_queue::handler -  { -  public: -    task_handler() -      : handler_queue::handler(0, 0) -    { -    } -  } task_handler_; - -  // The count of unfinished work. -  boost::detail::atomic_count outstanding_work_; - -  // The queue of handlers that are ready to be delivered. -  handler_queue handler_queue_; - -  // Flag to indicate that the dispatcher has been stopped. -  bool front_stopped_; -  bool back_stopped_; - -  // Flag to indicate that the dispatcher has been shut down. -  bool back_shutdown_; - -  // Structure containing information about an idle thread. -  struct idle_thread_info -  { -    event wakeup_event; -    idle_thread_info* next; -  }; - -  // The number of threads that are currently idle. -  idle_thread_info* back_first_idle_thread_; - -  // The thread that is currently blocked on the task. -  idle_thread_info* back_task_thread_; -}; - -} // namespace detail -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/task_io_service_operation.hpp b/3rdParty/Boost/src/boost/asio/detail/task_io_service_operation.hpp new file mode 100644 index 0000000..557f673 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/task_io_service_operation.hpp @@ -0,0 +1,71 @@ +// +// task_io_service_operation.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP +#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/task_io_service_fwd.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// Base class for all operations. A function pointer is used instead of virtual +// functions to avoid the associated overhead. +template <typename Task> +class task_io_service_operation +{ +public: +  void complete(task_io_service<Task>& owner) +  { +    func_(&owner, this, boost::system::error_code(), 0); +  } + +  void destroy() +  { +    func_(0, this, boost::system::error_code(), 0); +  } + +protected: +  typedef void (*func_type)(task_io_service<Task>*, +      task_io_service_operation*, boost::system::error_code, std::size_t); + +  task_io_service_operation(func_type func) +    : next_(0), +      func_(func) +  { +  } + +  // Prevents deletion through this type. +  ~task_io_service_operation() +  { +  } + +private: +  friend class op_queue_access; +  task_io_service_operation* next_; +  func_type func_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/system/error_code.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/thread.hpp b/3rdParty/Boost/src/boost/asio/detail/thread.hpp index 24a7a8c..3e2e215 100644 --- a/3rdParty/Boost/src/boost/asio/detail/thread.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/thread.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  # include <boost/asio/detail/null_thread.hpp>  #elif defined(BOOST_WINDOWS)  # if defined(UNDER_CE) @@ -39,7 +39,7 @@ namespace boost {  namespace asio {  namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  typedef null_thread thread;  #elif defined(BOOST_WINDOWS)  # if defined(UNDER_CE) diff --git a/3rdParty/Boost/src/boost/asio/detail/timer_op.hpp b/3rdParty/Boost/src/boost/asio/detail/timer_op.hpp new file mode 100644 index 0000000..9973d89 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/timer_op.hpp @@ -0,0 +1,46 @@ +// +// timer_op.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TIMER_OP_HPP +#define BOOST_ASIO_DETAIL_TIMER_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/operation.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class timer_op +  : public operation +{ +public: +  // The error code to be passed to the completion handler. +  boost::system::error_code ec_; + +protected: +  timer_op(func_type func) +    : operation(func) +  { +  } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_TIMER_OP_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/timer_queue.hpp b/3rdParty/Boost/src/boost/asio/detail/timer_queue.hpp index 35c8a77..164b342 100644 --- a/3rdParty/Boost/src/boost/asio/detail/timer_queue.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/timer_queue.hpp @@ -19,7 +19,6 @@  #include <boost/asio/detail/push_options.hpp>  #include <cstddef> -#include <functional>  #include <memory>  #include <vector>  #include <boost/config.hpp> @@ -27,9 +26,9 @@  #include <boost/asio/detail/pop_options.hpp>  #include <boost/asio/error.hpp> -#include <boost/asio/detail/handler_alloc_helpers.hpp>  #include <boost/asio/detail/hash_map.hpp> -#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/timer_op.hpp>  #include <boost/asio/detail/timer_queue_base.hpp>  namespace boost { @@ -50,50 +49,36 @@ public:    // Constructor.    timer_queue()      : timers_(), -      heap_(), -      cancelled_timers_(0), -      complete_timers_(0) +      heap_()    {    }    // Add a new timer to the queue. Returns true if this is the timer that is    // earliest in the queue, in which case the reactor's event demultiplexing    // function call may need to be interrupted and restarted. -  template <typename Handler> -  bool enqueue_timer(const time_type& time, Handler handler, void* token) +  bool enqueue_timer(const time_type& time, timer_op* op, void* token)    {      // Ensure that there is space for the timer in the heap. We reserve here so      // that the push_back below will not throw due to a reallocation failure.      heap_.reserve(heap_.size() + 1); -    // Create a new timer object. -    typedef timer<Handler> timer_type; -    typedef handler_alloc_traits<Handler, timer_type> alloc_traits; -    raw_handler_ptr<alloc_traits> raw_ptr(handler); -    handler_ptr<alloc_traits> new_timer(raw_ptr, time, handler, token);  -      // Insert the new timer into the hash. -    typedef typename hash_map<void*, timer_base*>::iterator iterator; -    typedef typename hash_map<void*, timer_base*>::value_type value_type; +    typedef typename hash_map<void*, timer>::iterator iterator; +    typedef typename hash_map<void*, timer>::value_type value_type;      std::pair<iterator, bool> result = -      timers_.insert(value_type(token, new_timer.get())); -    if (!result.second) +      timers_.insert(value_type(token, timer())); +    result.first->second.op_queue_.push(op); +    if (result.second)      { -      result.first->second->prev_ = new_timer.get(); -      new_timer.get()->next_ = result.first->second; -      result.first->second = new_timer.get(); +      // Put the new timer at the correct position in the heap. +      result.first->second.time_ = time; +      result.first->second.heap_index_ = heap_.size(); +      result.first->second.token_ = token; +      heap_.push_back(&result.first->second); +      up_heap(heap_.size() - 1);      } -    // Put the timer at the correct position in the heap. -    new_timer.get()->heap_index_ = heap_.size(); -    heap_.push_back(new_timer.get()); -    up_heap(heap_.size() - 1); -    bool is_first = (heap_[0] == new_timer.get()); - -    // Ownership of the timer is transferred to the timer queue. -    new_timer.release(); - -    return is_first; +    return (heap_[0] == &result.first->second);    }    // Whether there are no timers in the queue. @@ -103,226 +88,106 @@ public:    }    // Get the time for the timer that is earliest in the queue. -  virtual boost::posix_time::time_duration wait_duration() const +  virtual long wait_duration_msec(long max_duration) const    {      if (heap_.empty()) -      return boost::posix_time::pos_infin; -    return Time_Traits::to_posix_duration( +      return max_duration; + +    boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(          Time_Traits::subtract(heap_[0]->time_, Time_Traits::now())); -  } -  // Dispatch the timers that are earlier than the specified time. -  virtual void dispatch_timers() -  { -    const time_type now = Time_Traits::now(); -    while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_)) -    { -      timer_base* t = heap_[0]; -      remove_timer(t); -      t->result_ = boost::system::error_code(); -      t->prev_ = 0; -      t->next_ = complete_timers_; -      complete_timers_ = t; -    } -  } +    if (duration > boost::posix_time::milliseconds(max_duration)) +      duration = boost::posix_time::milliseconds(max_duration); +    else if (duration < boost::posix_time::milliseconds(0)) +      duration = boost::posix_time::milliseconds(0); -  // Cancel the timers with the given token. Any timers pending for the token -  // will be notified that they have been cancelled next time -  // dispatch_cancellations is called. Returns the number of timers that were -  // cancelled. -  std::size_t cancel_timer(void* timer_token) -  { -    std::size_t num_cancelled = 0; -    typedef typename hash_map<void*, timer_base*>::iterator iterator; -    iterator it = timers_.find(timer_token); -    if (it != timers_.end()) -    { -      timer_base* t = it->second; -      while (t) -      { -        timer_base* next = t->next_; -        remove_timer(t); -        t->prev_ = 0; -        t->next_ = cancelled_timers_; -        cancelled_timers_ = t; -        t = next; -        ++num_cancelled; -      } -    } -    return num_cancelled; +    return duration.total_milliseconds();    } -  // Dispatch any pending cancels for timers. -  virtual void dispatch_cancellations() +  // Get the time for the timer that is earliest in the queue. +  virtual long wait_duration_usec(long max_duration) const    { -    while (cancelled_timers_) -    { -      timer_base* this_timer = cancelled_timers_; -      this_timer->result_ = boost::asio::error::operation_aborted; -      cancelled_timers_ = this_timer->next_; -      this_timer->next_ = complete_timers_; -      complete_timers_ = this_timer; -    } +    if (heap_.empty()) +      return max_duration; + +    boost::posix_time::time_duration duration = Time_Traits::to_posix_duration( +        Time_Traits::subtract(heap_[0]->time_, Time_Traits::now())); + +    if (duration > boost::posix_time::microseconds(max_duration)) +      duration = boost::posix_time::microseconds(max_duration); +    else if (duration < boost::posix_time::microseconds(0)) +      duration = boost::posix_time::microseconds(0); + +    return duration.total_microseconds();    } -  // Complete any timers that are waiting to be completed. -  virtual void complete_timers() +  // Dequeue all timers not later than the current time. +  virtual void get_ready_timers(op_queue<operation>& ops)    { -    while (complete_timers_) +    const time_type now = Time_Traits::now(); +    while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))      { -      timer_base* this_timer = complete_timers_; -      complete_timers_ = this_timer->next_; -      this_timer->next_ = 0; -      this_timer->complete(); +      timer* t = heap_[0]; +      ops.push(t->op_queue_); +      remove_timer(t);      }    } -  // Destroy all timers. -  virtual void destroy_timers() +  // Dequeue all timers. +  virtual void get_all_timers(op_queue<operation>& ops)    { -    typename hash_map<void*, timer_base*>::iterator i = timers_.begin(); -    typename hash_map<void*, timer_base*>::iterator end = timers_.end(); +    typename hash_map<void*, timer>::iterator i = timers_.begin(); +    typename hash_map<void*, timer>::iterator end = timers_.end();      while (i != end)      { -      timer_base* t = i->second; -      typename hash_map<void*, timer_base*>::iterator old_i = i++; +      ops.push(i->second.op_queue_); +      typename hash_map<void*, timer>::iterator old_i = i++;        timers_.erase(old_i); -      destroy_timer_list(t);      } +      heap_.clear();      timers_.clear(); -    destroy_timer_list(cancelled_timers_); -    destroy_timer_list(complete_timers_);    } -private: -  // Base class for timer operations. Function pointers are used instead of -  // virtual functions to avoid the associated overhead. -  class timer_base +  // Cancel and dequeue the timers with the given token. +  std::size_t cancel_timer(void* timer_token, op_queue<operation>& ops)    { -  public: -    // Delete the timer and post the handler. -    void complete() -    { -      complete_func_(this, result_); -    } - -    // Delete the timer. -    void destroy() -    { -      destroy_func_(this); -    } - -  protected: -    typedef void (*complete_func_type)(timer_base*, -        const boost::system::error_code&); -    typedef void (*destroy_func_type)(timer_base*); - -    // Constructor. -    timer_base(complete_func_type complete_func, destroy_func_type destroy_func, -        const time_type& time, void* token) -      : complete_func_(complete_func), -        destroy_func_(destroy_func), -        time_(time), -        token_(token), -        next_(0), -        prev_(0), -        heap_index_( -            std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION()) -    { -    } - -    // Prevent deletion through this type. -    ~timer_base() +    std::size_t num_cancelled = 0; +    typedef typename hash_map<void*, timer>::iterator iterator; +    iterator it = timers_.find(timer_token); +    if (it != timers_.end())      { +      while (timer_op* op = it->second.op_queue_.front()) +      { +        op->ec_ = boost::asio::error::operation_aborted; +        it->second.op_queue_.pop(); +        ops.push(op); +        ++num_cancelled; +      } +      remove_timer(&it->second);      } +    return num_cancelled; +  } -  private: -    friend class timer_queue<Time_Traits>; - -    // The function to be called to delete the timer and post the handler. -    complete_func_type complete_func_; - -    // The function to be called to delete the timer. -    destroy_func_type destroy_func_; - -    // The result of the timer operation. -    boost::system::error_code result_; +private: +  // Structure representing a single outstanding timer. +  struct timer +  { +    timer() {} +    timer(const timer&) {} +    void operator=(const timer&) {}      // The time when the timer should fire.      time_type time_; -    // The token associated with the timer. -    void* token_; - -    // The next timer known to the queue. -    timer_base* next_; - -    // The previous timer known to the queue. -    timer_base* prev_; +    // The operations waiting on the timer. +    op_queue<timer_op> op_queue_;      // The index of the timer in the heap.      size_t heap_index_; -  }; -  // Adaptor class template for using handlers in timers. -  template <typename Handler> -  class timer -    : public timer_base -  { -  public: -    // Constructor. -    timer(const time_type& time, Handler handler, void* token) -      : timer_base(&timer<Handler>::complete_handler, -          &timer<Handler>::destroy_handler, time, token), -        handler_(handler) -    { -    } - -    // Delete the timer and post the handler. -    static void complete_handler(timer_base* base, -        const boost::system::error_code& result) -    { -      // Take ownership of the timer object. -      typedef timer<Handler> this_type; -      this_type* this_timer(static_cast<this_type*>(base)); -      typedef handler_alloc_traits<Handler, this_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer); - -      // Make a copy of the error_code and the handler so that the memory can -      // be deallocated before the upcall is made. -      boost::system::error_code ec(result); -      Handler handler(this_timer->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Make the upcall. -      handler(ec); -    } - -    // Delete the timer. -    static void destroy_handler(timer_base* base) -    { -      // Take ownership of the timer object. -      typedef timer<Handler> this_type; -      this_type* this_timer(static_cast<this_type*>(base)); -      typedef handler_alloc_traits<Handler, this_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer); - -      // 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. -      Handler handler(this_timer->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset(); -    } - -  private: -    Handler handler_; +    // The token associated with the timer. +    void* token_;    };    // Move the item at the given index up the heap to its correct position. @@ -359,7 +224,7 @@ private:    // Swap two entries in the heap.    void swap_heap(size_t index1, size_t index2)    { -    timer_base* tmp = heap_[index1]; +    timer* tmp = heap_[index1];      heap_[index1] = heap_[index2];      heap_[index2] = tmp;      heap_[index1]->heap_index_ = index1; @@ -367,7 +232,7 @@ private:    }    // Remove a timer from the heap and list of timers. -  void remove_timer(timer_base* t) +  void remove_timer(timer* t)    {      // Remove the timer from the heap.      size_t index = t->heap_index_; @@ -391,44 +256,17 @@ private:      }      // Remove the timer from the hash. -    typedef typename hash_map<void*, timer_base*>::iterator iterator; +    typedef typename hash_map<void*, timer>::iterator iterator;      iterator it = timers_.find(t->token_);      if (it != timers_.end()) -    { -      if (it->second == t) -        it->second = t->next_; -      if (t->prev_) -        t->prev_->next_ = t->next_; -      if (t->next_) -        t->next_->prev_ = t->prev_; -      if (it->second == 0) -        timers_.erase(it); -    } -  } - -  // 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; -    } +      timers_.erase(it);    }    // A hash of timer token to linked lists of timers. -  hash_map<void*, timer_base*> timers_; +  hash_map<void*, timer> timers_;    // The heap of timers, with the earliest timer at the front. -  std::vector<timer_base*> heap_; - -  // The list of timers to be cancelled. -  timer_base* cancelled_timers_; - -  // The list of timers waiting to be completed. -  timer_base* complete_timers_; +  std::vector<timer*> heap_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/timer_queue_base.hpp b/3rdParty/Boost/src/boost/asio/detail/timer_queue_base.hpp index cd6a0d3..074c2e1 100644 --- a/3rdParty/Boost/src/boost/asio/detail/timer_queue_base.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/timer_queue_base.hpp @@ -17,13 +17,9 @@  #include <boost/asio/detail/push_options.hpp> -#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time. - -#include <boost/asio/detail/push_options.hpp> -#include <boost/date_time/posix_time/posix_time_types.hpp> -#include <boost/asio/detail/pop_options.hpp> -  #include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/operation.hpp>  namespace boost {  namespace asio { @@ -33,6 +29,9 @@ class timer_queue_base    : private noncopyable  {  public: +  // Constructor. +  timer_queue_base() : next_(0) {} +    // Destructor.    virtual ~timer_queue_base() {} @@ -40,19 +39,22 @@ public:    virtual bool empty() const = 0;    // Get the time to wait until the next timer. -  virtual boost::posix_time::time_duration wait_duration() const = 0; +  virtual long wait_duration_msec(long max_duration) const = 0; + +  // Get the time to wait until the next timer. +  virtual long wait_duration_usec(long max_duration) const = 0; -  // Dispatch all ready timers. -  virtual void dispatch_timers() = 0; +  // Dequeue all ready timers. +  virtual void get_ready_timers(op_queue<operation>& ops) = 0; -  // Dispatch any pending cancels for timers. -  virtual void dispatch_cancellations() = 0; +  // Dequeue all timers. +  virtual void get_all_timers(op_queue<operation>& ops) = 0; -  // Complete all timers that are waiting to be completed. -  virtual void complete_timers() = 0; +private: +  friend class timer_queue_set; -  // Destroy all timers. -  virtual void destroy_timers() = 0; +  // Next timer queue in the set. +  timer_queue_base* next_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/timer_queue_fwd.hpp b/3rdParty/Boost/src/boost/asio/detail/timer_queue_fwd.hpp new file mode 100644 index 0000000..b8bc5f2 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/timer_queue_fwd.hpp @@ -0,0 +1,33 @@ +// +// timer_queue_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TIMER_QUEUE_FWD_HPP +#define BOOST_ASIO_DETAIL_TIMER_QUEUE_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Time_Traits> +class timer_queue; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_FWD_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/timer_queue_set.hpp b/3rdParty/Boost/src/boost/asio/detail/timer_queue_set.hpp new file mode 100644 index 0000000..a92a6b9 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/timer_queue_set.hpp @@ -0,0 +1,117 @@ +// +// timer_queue_set.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TIMER_QUEUE_SET_HPP +#define BOOST_ASIO_DETAIL_TIMER_QUEUE_SET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/timer_queue_base.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class timer_queue_set +{ +public: +  // Constructor. +  timer_queue_set() +    : first_(0) +  { +  } + +  // Add a timer queue to the set. +  void insert(timer_queue_base* q) +  { +    q->next_ = first_; +    first_ = q; +  } + +  // Remove a timer queue from the set. +  void erase(timer_queue_base* q) +  { +    if (first_) +    { +      if (q == first_) +      { +        first_ = q->next_; +        q->next_ = 0; +        return; +      } + +      for (timer_queue_base* p = first_; p->next_; p = p->next_) +      { +        if (p->next_ == q) +        { +          p->next_ = q->next_; +          q->next_ = 0; +          return; +        } +      } +    } +  } + +  // Determine whether all queues are empty. +  bool all_empty() const +  { +    for (timer_queue_base* p = first_; p; p = p->next_) +      if (!p->empty()) +        return false; +    return true; +  } + +  // Get the wait duration in milliseconds. +  long wait_duration_msec(long max_duration) const +  { +    long min_duration = max_duration; +    for (timer_queue_base* p = first_; p; p = p->next_) +      min_duration = p->wait_duration_msec(min_duration); +    return min_duration; +  } + +  // Get the wait duration in microseconds. +  long wait_duration_usec(long max_duration) const +  { +    long min_duration = max_duration; +    for (timer_queue_base* p = first_; p; p = p->next_) +      min_duration = p->wait_duration_usec(min_duration); +    return min_duration; +  } + +  // Dequeue all ready timers. +  void get_ready_timers(op_queue<operation>& ops) +  { +    for (timer_queue_base* p = first_; p; p = p->next_) +      p->get_ready_timers(ops); +  } + +  // Dequeue all timers. +  void get_all_timers(op_queue<operation>& ops) +  { +    for (timer_queue_base* p = first_; p; p = p->next_) +      p->get_all_timers(ops); +  } + +private: +  timer_queue_base* first_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_SET_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/timer_scheduler.hpp b/3rdParty/Boost/src/boost/asio/detail/timer_scheduler.hpp new file mode 100644 index 0000000..bc837ee --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/timer_scheduler.hpp @@ -0,0 +1,36 @@ +// +// timer_scheduler.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TIMER_SCHEDULER_HPP +#define BOOST_ASIO_DETAIL_TIMER_SCHEDULER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/timer_scheduler_fwd.hpp> + +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_service.hpp> +#elif defined(BOOST_ASIO_HAS_EPOLL) +# include <boost/asio/detail/epoll_reactor.hpp> +#elif defined(BOOST_ASIO_HAS_KQUEUE) +# include <boost/asio/detail/kqueue_reactor.hpp> +#elif defined(BOOST_ASIO_HAS_DEV_POLL) +# include <boost/asio/detail/dev_poll_reactor.hpp> +#else +# include <boost/asio/detail/select_reactor.hpp> +#endif + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_TIMER_SCHEDULER_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/timer_scheduler_fwd.hpp b/3rdParty/Boost/src/boost/asio/detail/timer_scheduler_fwd.hpp new file mode 100644 index 0000000..9d0b1e6 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/timer_scheduler_fwd.hpp @@ -0,0 +1,48 @@ +// +// timer_scheduler_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP +#define BOOST_ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/dev_poll_reactor_fwd.hpp> +#include <boost/asio/detail/epoll_reactor_fwd.hpp> +#include <boost/asio/detail/kqueue_reactor_fwd.hpp> +#include <boost/asio/detail/select_reactor_fwd.hpp> +#include <boost/asio/detail/win_iocp_io_service_fwd.hpp> + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_HAS_IOCP) +typedef win_iocp_io_service timer_scheduler; +#elif defined(BOOST_ASIO_HAS_EPOLL) +typedef epoll_reactor timer_scheduler; +#elif defined(BOOST_ASIO_HAS_KQUEUE) +typedef kqueue_reactor timer_scheduler; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) +typedef dev_poll_reactor timer_scheduler; +#else +typedef select_reactor<false> timer_scheduler; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/tss_ptr.hpp b/3rdParty/Boost/src/boost/asio/detail/tss_ptr.hpp index 9af4965..7ccfcf3 100644 --- a/3rdParty/Boost/src/boost/asio/detail/tss_ptr.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/tss_ptr.hpp @@ -21,7 +21,7 @@  #include <boost/config.hpp>  #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)  # include <boost/asio/detail/null_tss_ptr.hpp>  #elif defined(BOOST_WINDOWS)  # include <boost/asio/detail/win_tss_ptr.hpp> @@ -37,7 +37,7 @@ namespace detail {  template <typename T>  class tss_ptr -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)    : public null_tss_ptr<T>  #elif defined(BOOST_WINDOWS)    : public win_tss_ptr<T> @@ -48,7 +48,7 @@ class tss_ptr  public:    void operator=(T* value)    { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)      null_tss_ptr<T>::operator=(value);  #elif defined(BOOST_WINDOWS)      win_tss_ptr<T>::operator=(value); diff --git a/3rdParty/Boost/src/boost/asio/detail/win_event.hpp b/3rdParty/Boost/src/boost/asio/detail/win_event.hpp index 637b580..bddf09d 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_event.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_event.hpp @@ -71,6 +71,15 @@ public:      ::SetEvent(event_);    } +  // Signal the event and unlock the mutex. +  template <typename Lock> +  void signal_and_unlock(Lock& lock) +  { +    BOOST_ASSERT(lock.locked()); +    lock.unlock(); +    ::SetEvent(event_); +  } +    // Reset the event.    template <typename Lock>    void clear(Lock& lock) diff --git a/3rdParty/Boost/src/boost/asio/detail/win_fenced_block.hpp b/3rdParty/Boost/src/boost/asio/detail/win_fenced_block.hpp new file mode 100644 index 0000000..ff4a21c --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/win_fenced_block.hpp @@ -0,0 +1,77 @@ +// +// win_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_WIN_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/push_options.hpp> +#include <boost/config.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#if defined(BOOST_WINDOWS) && !defined(UNDER_CE) + +#include <boost/asio/detail/socket_types.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class win_fenced_block +  : private noncopyable +{ +public: +  // Constructor. +  win_fenced_block() +  { +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +# if defined(_M_IX86) +#  pragma warning(push) +#  pragma warning(disable:4793) +    LONG barrier; +    __asm { xchg barrier, eax } +#  pragma warning(pop) +# endif // defined(_M_IX86) +#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +    MemoryBarrier(); +#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +  } + +  // Destructor. +  ~win_fenced_block() +  { +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +# if defined(_M_IX86) +#  pragma warning(push) +#  pragma warning(disable:4793) +    LONG barrier; +    __asm { xchg barrier, eax } +#  pragma warning(pop) +# endif // defined(_M_IX86) +#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +    MemoryBarrier(); +#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +  } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE) + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_WIN_FENCED_BLOCK_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_handle_service.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_handle_service.hpp index 6998d57..a6d6599 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_iocp_handle_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_handle_service.hpp @@ -26,13 +26,14 @@  #include <boost/cstdint.hpp>  #include <boost/asio/detail/pop_options.hpp> -#include <boost/asio/buffer.hpp>  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp>  #include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/buffer_sequence_adapter.hpp>  #include <boost/asio/detail/handler_alloc_helpers.hpp>  #include <boost/asio/detail/handler_invoke_helpers.hpp>  #include <boost/asio/detail/mutex.hpp> +#include <boost/asio/detail/operation.hpp>  #include <boost/asio/detail/win_iocp_io_service.hpp>  namespace boost { @@ -40,12 +41,8 @@ namespace asio {  namespace detail {  class win_iocp_handle_service -  : public boost::asio::detail::service_base<win_iocp_handle_service>  {  public: -  // Base class for all operations. -  typedef win_iocp_io_service::operation operation; -    // The native type of a stream handle.    typedef HANDLE native_type; @@ -81,8 +78,7 @@ public:    };    win_iocp_handle_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base<win_iocp_handle_service>(io_service), -      iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)), +    : iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),        mutex_(),        impl_list_(0)    { @@ -307,16 +303,9 @@ public:        return 0;      } -    // Find first buffer of non-zero length. -    boost::asio::const_buffer buffer; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    for (DWORD i = 0; iter != end; ++iter, ++i) -    { -      buffer = boost::asio::const_buffer(*iter); -      if (boost::asio::buffer_size(buffer) != 0) -        break; -    } +    boost::asio::const_buffer buffer = +      buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence>::first(buffers);      // A request to write 0 bytes on a handle is a no-op.      if (boost::asio::buffer_size(buffer) == 0) @@ -365,79 +354,48 @@ public:    }    template <typename ConstBufferSequence, typename Handler> -  class write_operation -    : public operation +  class write_op : public operation    {    public: -    write_operation(win_iocp_io_service& io_service, -        const ConstBufferSequence& buffers, Handler handler) -      : operation(io_service, -          &write_operation<ConstBufferSequence, Handler>::do_completion_impl, -          &write_operation<ConstBufferSequence, Handler>::destroy_impl), -        work_(io_service.get_io_service()), +    write_op(const ConstBufferSequence& buffers, Handler handler) +      : operation(&write_op::do_complete),          buffers_(buffers),          handler_(handler)      {      } -  private: -    static void do_completion_impl(operation* op, -        DWORD last_error, size_t bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t bytes_transferred)      {        // Take ownership of the operation object. -      typedef write_operation<ConstBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +      write_op* o(static_cast<write_op*>(base)); +      typedef handler_alloc_traits<Handler, write_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Check whether buffers are still valid. -      typename ConstBufferSequence::const_iterator iter -        = handler_op->buffers_.begin(); -      typename ConstBufferSequence::const_iterator end -        = handler_op->buffers_.end(); -      while (iter != end) +      // Make the upcall if required. +      if (owner)        { -        boost::asio::const_buffer buffer(*iter); -        boost::asio::buffer_cast<const char*>(buffer); -        ++iter; -      } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +        // Check whether buffers are still valid. +        buffer_sequence_adapter<boost::asio::const_buffer, +            ConstBufferSequence>::validate(o->buffers_);  #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Call the handler. -      boost::system::error_code ec(last_error, -          boost::asio::error::get_system_category()); -      boost_asio_handler_invoke_helpers::invoke( -          bind_handler(handler, ec, bytes_transferred), handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef write_operation<ConstBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset(); +        // 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, std::size_t> +          handler(o->handler_, ec, bytes_transferred); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      } -    boost::asio::io_service::work work_; +  private:      ConstBufferSequence buffers_;      Handler handler_;    }; @@ -457,65 +415,16 @@ public:    void async_write_some_at(implementation_type& impl, boost::uint64_t offset,        const ConstBufferSequence& buffers, Handler handler)    { -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -      // Allocate and construct an operation to wrap the handler. -    typedef write_operation<ConstBufferSequence, Handler> value_type; +    typedef write_op<ConstBufferSequence, 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, iocp_service_, buffers, handler); - -    if (!is_open(impl)) -    { -      ptr.get()->on_immediate_completion(WSAEBADF, 0); -      ptr.release(); -      return; -    } - -    // Find first buffer of non-zero length. -    boost::asio::const_buffer buffer; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    for (DWORD i = 0; iter != end; ++iter, ++i) -    { -      buffer = boost::asio::const_buffer(*iter); -      if (boost::asio::buffer_size(buffer) != 0) -        break; -    } - -    // A request to write 0 bytes on a handle is a no-op. -    if (boost::asio::buffer_size(buffer) == 0) -    { -      ptr.get()->on_immediate_completion(0, 0); -      ptr.release(); -      return; -    } - -    // Write the data. -    DWORD bytes_transferred = 0; -    ptr.get()->Offset = offset & 0xFFFFFFFF; -    ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; -    BOOL ok = ::WriteFile(impl.handle_, -        boost::asio::buffer_cast<LPCVOID>(buffer), -        static_cast<DWORD>(boost::asio::buffer_size(buffer)), -        &bytes_transferred, ptr.get()); -    DWORD last_error = ::GetLastError(); +    handler_ptr<alloc_traits> ptr(raw_ptr, buffers, handler); -    // Check if the operation completed immediately. -    if (!ok && last_error != ERROR_IO_PENDING) -    { -      ptr.get()->on_immediate_completion(last_error, bytes_transferred); -      ptr.release(); -    } -    else -    { -      ptr.get()->on_pending(); -      ptr.release(); -    } +    start_write_op(impl, offset, +        buffer_sequence_adapter<boost::asio::const_buffer, +          ConstBufferSequence>::first(buffers), ptr.get()); +    ptr.release();    }    // Read some data. Returns the number of bytes received. @@ -537,16 +446,9 @@ public:        return 0;      } -    // Find first buffer of non-zero length. -    boost::asio::mutable_buffer buffer; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    for (DWORD i = 0; iter != end; ++iter, ++i) -    { -      buffer = boost::asio::mutable_buffer(*iter); -      if (boost::asio::buffer_size(buffer) != 0) -        break; -    } +    boost::asio::mutable_buffer buffer = +      buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence>::first(buffers);      // A request to read 0 bytes on a stream handle is a no-op.      if (boost::asio::buffer_size(buffer) == 0) @@ -609,89 +511,54 @@ public:    }    template <typename MutableBufferSequence, typename Handler> -  class read_operation -    : public operation +  class read_op : public operation    {    public: -    read_operation(win_iocp_io_service& io_service, -        const MutableBufferSequence& buffers, Handler handler) -      : operation(io_service, -          &read_operation< -            MutableBufferSequence, Handler>::do_completion_impl, -          &read_operation< -            MutableBufferSequence, Handler>::destroy_impl), -        work_(io_service.get_io_service()), +    read_op(const MutableBufferSequence& buffers, Handler handler) +      : operation(&read_op::do_complete),          buffers_(buffers),          handler_(handler)      {      } -  private: -    static void do_completion_impl(operation* op, -        DWORD last_error, size_t bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t bytes_transferred)      {        // Take ownership of the operation object. -      typedef read_operation<MutableBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +      read_op* o(static_cast<read_op*>(base)); +      typedef handler_alloc_traits<Handler, read_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Check whether buffers are still valid. -      typename MutableBufferSequence::const_iterator iter -        = handler_op->buffers_.begin(); -      typename MutableBufferSequence::const_iterator end -        = handler_op->buffers_.end(); -      while (iter != end) +      // Make the upcall if required. +      if (owner)        { -        boost::asio::mutable_buffer buffer(*iter); -        boost::asio::buffer_cast<char*>(buffer); -        ++iter; -      } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +        // Check whether buffers are still valid. +        buffer_sequence_adapter<boost::asio::mutable_buffer, +            MutableBufferSequence>::validate(o->buffers_);  #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Check for the end-of-file condition. -      boost::system::error_code ec(last_error, -          boost::asio::error::get_system_category()); -      if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF) -      { -        ec = boost::asio::error::eof; -      } - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Call the handler. -      boost_asio_handler_invoke_helpers::invoke( -        bind_handler(handler, ec, bytes_transferred), handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef read_operation<MutableBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef boost::asio::detail::handler_alloc_traits< -        Handler, op_type> alloc_traits; -      boost::asio::detail::handler_ptr<alloc_traits> ptr( -        handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; +        // Map non-portable errors to their portable counterparts. +        if (ec.value() == ERROR_HANDLE_EOF) +        { +          ec = boost::asio::error::eof; +        } -      // Free the memory associated with the handler. -      ptr.reset(); +        // 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, std::size_t> +          handler(o->handler_, ec, bytes_transferred); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      } -    boost::asio::io_service::work work_; +  private:      MutableBufferSequence buffers_;      Handler handler_;    }; @@ -712,63 +579,16 @@ public:    void async_read_some_at(implementation_type& impl, boost::uint64_t offset,        const MutableBufferSequence& buffers, Handler handler)    { -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -      // Allocate and construct an operation to wrap the handler. -    typedef read_operation<MutableBufferSequence, Handler> value_type; +    typedef read_op<MutableBufferSequence, 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, iocp_service_, buffers, handler); +    handler_ptr<alloc_traits> ptr(raw_ptr, buffers, handler); -    if (!is_open(impl)) -    { -      ptr.get()->on_immediate_completion(WSAEBADF, 0); -      ptr.release(); -      return; -    } - -    // Find first buffer of non-zero length. -    boost::asio::mutable_buffer buffer; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    for (DWORD i = 0; iter != end; ++iter, ++i) -    { -      buffer = boost::asio::mutable_buffer(*iter); -      if (boost::asio::buffer_size(buffer) != 0) -        break; -    } - -    // A request to receive 0 bytes on a stream handle is a no-op. -    if (boost::asio::buffer_size(buffer) == 0) -    { -      ptr.get()->on_immediate_completion(0, 0); -      ptr.release(); -      return; -    } - -    // Read some data. -    DWORD bytes_transferred = 0; -    ptr.get()->Offset = offset & 0xFFFFFFFF; -    ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; -    BOOL ok = ::ReadFile(impl.handle_, -        boost::asio::buffer_cast<LPVOID>(buffer), -        static_cast<DWORD>(boost::asio::buffer_size(buffer)), -        &bytes_transferred, ptr.get()); -    DWORD last_error = ::GetLastError(); -    if (!ok && last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA) -    { -      ptr.get()->on_immediate_completion(last_error, bytes_transferred); -      ptr.release(); -    } -    else -    { -      ptr.get()->on_pending(); -      ptr.release(); -    } +    start_read_op(impl, offset, +        buffer_sequence_adapter<boost::asio::mutable_buffer, +          MutableBufferSequence>::first(buffers), ptr.get()); +    ptr.release();    }  private: @@ -794,6 +614,95 @@ private:    void async_read_some_at(implementation_type& impl, boost::uint64_t offset,        const null_buffers& buffers, Handler handler); +  // Helper function to start a write operation. +  void start_write_op(implementation_type& impl, boost::uint64_t offset, +      const boost::asio::const_buffer& buffer, operation* op) +  { +    update_cancellation_thread_id(impl); +    iocp_service_.work_started(); + +    if (!is_open(impl)) +    { +      iocp_service_.on_completion(op, boost::asio::error::bad_descriptor); +    } +    else if (boost::asio::buffer_size(buffer) == 0) +    { +      // A request to write 0 bytes on a handle is a no-op. +      iocp_service_.on_completion(op); +    } +    else +    { +      DWORD bytes_transferred = 0; +      op->Offset = offset & 0xFFFFFFFF; +      op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; +      BOOL ok = ::WriteFile(impl.handle_, +          boost::asio::buffer_cast<LPCVOID>(buffer), +          static_cast<DWORD>(boost::asio::buffer_size(buffer)), +          &bytes_transferred, op); +      DWORD last_error = ::GetLastError(); +      if (!ok && last_error != ERROR_IO_PENDING +          && last_error != ERROR_MORE_DATA) +      { +        iocp_service_.on_completion(op, last_error, bytes_transferred); +      } +      else +      { +        iocp_service_.on_pending(op); +      } +    } +  } + +  // Helper function to start a read operation. +  void start_read_op(implementation_type& impl, boost::uint64_t offset, +      const boost::asio::mutable_buffer& buffer, operation* op) +  { +    update_cancellation_thread_id(impl); +    iocp_service_.work_started(); + +    if (!is_open(impl)) +    { +      iocp_service_.on_completion(op, boost::asio::error::bad_descriptor); +    } +    else if (boost::asio::buffer_size(buffer) == 0) +    { +      // A request to read 0 bytes on a handle is a no-op. +      iocp_service_.on_completion(op); +    } +    else +    { +      DWORD bytes_transferred = 0; +      op->Offset = offset & 0xFFFFFFFF; +      op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; +      BOOL ok = ::ReadFile(impl.handle_, +          boost::asio::buffer_cast<LPVOID>(buffer), +          static_cast<DWORD>(boost::asio::buffer_size(buffer)), +          &bytes_transferred, op); +      DWORD last_error = ::GetLastError(); +      if (!ok && last_error != ERROR_IO_PENDING +          && last_error != ERROR_MORE_DATA) +      { +        iocp_service_.on_completion(op, last_error, bytes_transferred); +      } +      else +      { +        iocp_service_.on_pending(op); +      } +    } +  } + +  // Update the ID of the thread from which cancellation is safe. +  void update_cancellation_thread_id(implementation_type& impl) +  { +#if defined(BOOST_ASIO_ENABLE_CANCELIO) +    if (impl.safe_cancellation_thread_id_ == 0) +      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); +    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) +      impl.safe_cancellation_thread_id_ = ~DWORD(0); +#else // defined(BOOST_ASIO_ENABLE_CANCELIO) +    (void)impl; +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) +  } +    // Helper function to close a handle when the associated object is being    // destroyed.    void close_for_destruction(implementation_type& impl) diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp index 1dfb9a1..83b16bf 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp @@ -29,122 +29,37 @@  #include <boost/asio/io_service.hpp>  #include <boost/asio/detail/call_stack.hpp> +#include <boost/asio/detail/completion_handler.hpp> +#include <boost/asio/detail/fenced_block.hpp>  #include <boost/asio/detail/handler_alloc_helpers.hpp>  #include <boost/asio/detail/handler_invoke_helpers.hpp> +#include <boost/asio/detail/mutex.hpp> +#include <boost/asio/detail/op_queue.hpp>  #include <boost/asio/detail/service_base.hpp>  #include <boost/asio/detail/socket_types.hpp> -#include <boost/asio/detail/timer_queue.hpp> -#include <boost/asio/detail/mutex.hpp> +#include <boost/asio/detail/timer_op.hpp> +#include <boost/asio/detail/timer_queue_base.hpp> +#include <boost/asio/detail/timer_queue_fwd.hpp> +#include <boost/asio/detail/timer_queue_set.hpp> +#include <boost/asio/detail/win_iocp_operation.hpp>  namespace boost {  namespace asio {  namespace detail { +class timer_op; +  class win_iocp_io_service    : public boost::asio::detail::service_base<win_iocp_io_service>  {  public: -  // Base class for all operations. A function pointer is used instead of -  // virtual functions to avoid the associated overhead. -  // -  // This class inherits from OVERLAPPED so that we can downcast to get back to -  // the operation pointer from the LPOVERLAPPED out parameter of -  // GetQueuedCompletionStatus. -  class operation; -  friend class operation; -  class operation -    : public OVERLAPPED -  { -  public: -    typedef void (*invoke_func_type)(operation*, DWORD, size_t); -    typedef void (*destroy_func_type)(operation*); - -    operation(win_iocp_io_service& iocp_service, -        invoke_func_type invoke_func, destroy_func_type destroy_func) -      : iocp_service_(iocp_service), -        ready_(0), -        last_error_(~DWORD(0)), -        bytes_transferred_(0), -        invoke_func_(invoke_func), -        destroy_func_(destroy_func) -    { -      Internal = 0; -      InternalHigh = 0; -      Offset = 0; -      OffsetHigh = 0; -      hEvent = 0; - -      ::InterlockedIncrement(&iocp_service_.outstanding_operations_); -    } - -    void reset() -    { -      Internal = 0; -      InternalHigh = 0; -      Offset = 0; -      OffsetHigh = 0; -      hEvent = 0; -      ready_ = 0; -      last_error_ = ~DWORD(0); -      bytes_transferred_ = 0; -    } - -    void on_pending() -    { -      if (::InterlockedCompareExchange(&ready_, 1, 0) == 1) -        iocp_service_.post_completion(this, last_error_, bytes_transferred_); -    } - -    void on_immediate_completion(DWORD last_error, DWORD bytes_transferred) -    { -      ready_ = 1; -      iocp_service_.post_completion(this, last_error, bytes_transferred); -    } - -    bool on_completion(DWORD last_error, DWORD bytes_transferred) -    { -      if (last_error_ == ~DWORD(0)) -      { -        last_error_ = last_error; -        bytes_transferred_ = bytes_transferred; -      } - -      if (::InterlockedCompareExchange(&ready_, 1, 0) == 1) -      { -        invoke_func_(this, last_error_, bytes_transferred_); -        return true; -      } - -      return false; -    } - -    void destroy() -    { -      destroy_func_(this); -    } - -  protected: -    // Prevent deletion through this type. -    ~operation() -    { -      ::InterlockedDecrement(&iocp_service_.outstanding_operations_); -    } - -  private: -    win_iocp_io_service& iocp_service_; -    long ready_; -    DWORD last_error_; -    DWORD bytes_transferred_; -    invoke_func_type invoke_func_; -    destroy_func_type destroy_func_; -  }; +  typedef win_iocp_operation operation;    // Constructor.    win_iocp_io_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<win_iocp_io_service>(io_service),        iocp_(),        outstanding_work_(0), -      outstanding_operations_(0),        stopped_(0),        shutdown_(0),        timer_thread_(0), @@ -172,24 +87,34 @@ public:    {      ::InterlockedExchange(&shutdown_, 1); -    while (::InterlockedExchangeAdd(&outstanding_operations_, 0) > 0) +    while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)      { -      DWORD bytes_transferred = 0; -#if defined(WINVER) && (WINVER < 0x0500) -      DWORD completion_key = 0; -#else -      DWORD_PTR completion_key = 0; -#endif -      LPOVERLAPPED overlapped = 0; -      ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, -          &completion_key, &overlapped, INFINITE); -      if (overlapped) -        static_cast<operation*>(overlapped)->destroy(); +      op_queue<operation> ops; +      timer_queues_.get_all_timers(ops); +      ops.push(completed_ops_); +      if (!ops.empty()) +      { +        while (operation* op = ops.front()) +        { +          ops.pop(); +          ::InterlockedDecrement(&outstanding_work_); +          op->destroy(); +        } +      } +      else +      { +        DWORD bytes_transferred = 0; +        dword_ptr_t completion_key = 0; +        LPOVERLAPPED overlapped = 0; +        ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, +            &completion_key, &overlapped, max_timeout); +        if (overlapped) +        { +          ::InterlockedDecrement(&outstanding_work_); +          static_cast<operation*>(overlapped)->destroy(); +        } +      }      } - -    for (std::size_t i = 0; i < timer_queues_.size(); ++i) -      timer_queues_[i]->destroy_timers(); -    timer_queues_.clear();    }    // Initialise the task. Nothing to do here. @@ -219,6 +144,7 @@ public:    {      if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)      { +      stop();        ec = boost::system::error_code();        return 0;      } @@ -237,6 +163,7 @@ public:    {      if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)      { +      stop();        ec = boost::system::error_code();        return 0;      } @@ -251,6 +178,7 @@ public:    {      if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)      { +      stop();        ec = boost::system::error_code();        return 0;      } @@ -269,6 +197,7 @@ public:    {      if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)      { +      stop();        ec = boost::system::error_code();        return 0;      } @@ -319,7 +248,10 @@ public:    void dispatch(Handler handler)    {      if (call_stack<win_iocp_io_service>::contains(this)) +    { +      boost::asio::detail::fenced_block b;        boost_asio_handler_invoke_helpers::invoke(handler, handler); +    }      else        post(handler);    } @@ -328,37 +260,128 @@ public:    template <typename Handler>    void post(Handler handler)    { -    // If the service has been shut down we silently discard the handler. -    if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) -      return; -      // Allocate and construct an operation to wrap the handler. -    typedef handler_operation<Handler> value_type; +    typedef completion_handler<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, *this, handler); +    handler_ptr<alloc_traits> ptr(raw_ptr, handler); + +    post_immediate_completion(ptr.get()); +    ptr.release(); +  } + +  // Request invocation of the given operation and return immediately. Assumes +  // that work_started() has not yet been called for the operation. +  void post_immediate_completion(operation* op) +  { +    work_started(); +    post_deferred_completion(op); +  } + +  // Request invocation of the given operation and return immediately. Assumes +  // that work_started() was previously called for the operation. +  void post_deferred_completion(operation* op) +  { +    // Flag the operation as ready. +    op->ready_ = 1;      // Enqueue the operation on the I/O completion port. -    ptr.get()->on_immediate_completion(0, 0); +    if (!::PostQueuedCompletionStatus(iocp_.handle, +          0, overlapped_contains_result, op)) +    { +      // Out of resources. Put on completed queue instead. +      boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); +      completed_ops_.push(op); +    } +  } -    // Operation has been successfully posted. -    ptr.release(); +  // Request invocation of the given operation and return immediately. Assumes +  // that work_started() was previously called for the operations. +  void post_deferred_completions(op_queue<operation>& ops) +  { +    while (operation* op = ops.front()) +    { +      ops.pop(); + +      // Flag the operation as ready. +      op->ready_ = 1; + +      // Enqueue the operation on the I/O completion port. +      if (!::PostQueuedCompletionStatus(iocp_.handle, +            0, overlapped_contains_result, op)) +      { +        // Out of resources. Put on completed queue instead. +        boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); +        completed_ops_.push(op); +        completed_ops_.push(ops); +      } +    }    } -  // Request invocation of the given OVERLAPPED-derived operation. -  void post_completion(operation* op, DWORD op_last_error, -      DWORD bytes_transferred) +  // Called after starting an overlapped I/O operation that did not complete +  // immediately. The caller must have already called work_started() prior to +  // starting the operation. +  void on_pending(operation* op)    { +    if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1) +    { +      // Enqueue the operation on the I/O completion port. +      if (!::PostQueuedCompletionStatus(iocp_.handle, +            0, overlapped_contains_result, op)) +      { +        // Out of resources. Put on completed queue instead. +        boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); +        completed_ops_.push(op); +      } +    } +  } + +  // Called after starting an overlapped I/O operation that completed +  // immediately. The caller must have already called work_started() prior to +  // starting the operation. +  void on_completion(operation* op, +      DWORD last_error = 0, DWORD bytes_transferred = 0) +  { +    // Flag that the operation is ready for invocation. +    op->ready_ = 1; + +    // Store results in the OVERLAPPED structure. +    op->Internal = reinterpret_cast<ulong_ptr_t>( +        &boost::asio::error::get_system_category()); +    op->Offset = last_error; +    op->OffsetHigh = bytes_transferred; +      // Enqueue the operation on the I/O completion port.      if (!::PostQueuedCompletionStatus(iocp_.handle, -          bytes_transferred, op_last_error, op)) +          0, overlapped_contains_result, op))      { -      DWORD last_error = ::GetLastError(); -      boost::system::system_error e( -          boost::system::error_code(last_error, -            boost::asio::error::get_system_category()), -          "pqcs"); -      boost::throw_exception(e); +      // Out of resources. Put on completed queue instead. +      boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); +      completed_ops_.push(op); +    } +  } + +  // Called after starting an overlapped I/O operation that completed +  // immediately. The caller must have already called work_started() prior to +  // starting the operation. +  void on_completion(operation* op, +      const boost::system::error_code& ec, DWORD bytes_transferred = 0) +  { +    // Flag that the operation is ready for invocation. +    op->ready_ = 1; + +    // Store results in the OVERLAPPED structure. +    op->Internal = reinterpret_cast<ulong_ptr_t>(&ec.category()); +    op->Offset = ec.value(); +    op->OffsetHigh = bytes_transferred; + +    // Enqueue the operation on the I/O completion port. +    if (!::PostQueuedCompletionStatus(iocp_.handle, +          0, overlapped_contains_result, op)) +    { +      // Out of resources. Put on completed queue instead. +      boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); +      completed_ops_.push(op);      }    } @@ -367,7 +390,7 @@ public:    void add_timer_queue(timer_queue<Time_Traits>& timer_queue)    {      boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); -    timer_queues_.push_back(&timer_queue); +    timer_queues_.insert(&timer_queue);    }    // Remove a timer queue from the service. @@ -375,36 +398,28 @@ public:    void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)    {      boost::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; -      } -    } +    timer_queues_.erase(&timer_queue);    } -  // 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> +  // Schedule a new operation in the given timer queue to expire at the +  // specified absolute time. +  template <typename Time_Traits>    void schedule_timer(timer_queue<Time_Traits>& timer_queue, -      const typename Time_Traits::time_type& time, Handler handler, void* token) +      const typename Time_Traits::time_type& time, timer_op* op, void* token)    {      // If the service has been shut down we silently discard the timer.      if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)        return;      boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); -    if (timer_queue.enqueue_timer(time, handler, token)) +    bool interrupt = timer_queue.enqueue_timer(time, op, token); +    work_started(); +    if (interrupt && !timer_interrupt_issued_)      { -      if (!timer_interrupt_issued_) -      { -        timer_interrupt_issued_ = true; -        lock.unlock(); -        ::PostQueuedCompletionStatus(iocp_.handle, -            0, steal_timer_dispatching, 0); -      } +      timer_interrupt_issued_ = true; +      lock.unlock(); +      ::PostQueuedCompletionStatus(iocp_.handle, +          0, steal_timer_dispatching, 0);      }    } @@ -418,7 +433,9 @@ public:        return 0;      boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); -    std::size_t n = timer_queue.cancel_timer(token); +    op_queue<operation> ops; +    std::size_t n = timer_queue.cancel_timer(token, ops); +    post_deferred_completions(ops);      if (n > 0 && !timer_interrupt_issued_)      {        timer_interrupt_issued_ = true; @@ -430,6 +447,14 @@ public:    }  private: +#if defined(WINVER) && (WINVER < 0x0500) +  typedef DWORD dword_ptr_t; +  typedef ULONG ulong_ptr_t; +#else // defined(WINVER) && (WINVER < 0x0500) +  typedef DWORD_PTR dword_ptr_t; +  typedef ULONG_PTR ulong_ptr_t; +#endif // defined(WINVER) && (WINVER < 0x0500) +    // 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). @@ -454,11 +479,7 @@ private:        // Get the next operation from the queue.        DWORD bytes_transferred = 0; -#if defined(WINVER) && (WINVER < 0x0500) -      DWORD completion_key = 0; -#else -      DWORD_PTR completion_key = 0; -#endif +      dword_ptr_t completion_key = 0;        LPOVERLAPPED overlapped = 0;        ::SetLastError(0);        BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, @@ -468,32 +489,11 @@ private:        // Dispatch any pending timers.        if (dispatching_timers)        { -        try -        { -          boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); -          if (!timer_queues_.empty()) -          { -            timer_queues_copy_ = timer_queues_; -            for (std::size_t i = 0; i < timer_queues_copy_.size(); ++i) -            { -              timer_queues_copy_[i]->dispatch_timers(); -              timer_queues_copy_[i]->dispatch_cancellations(); -              timer_queues_copy_[i]->complete_timers(); -            } -          } -        } -        catch (...) -        { -          // Transfer responsibility for dispatching timers to another thread. -          if (::InterlockedCompareExchange(&timer_thread_, -                0, this_thread_id) == this_thread_id) -          { -            ::PostQueuedCompletionStatus(iocp_.handle, -                0, transfer_timer_dispatching, 0); -          } - -          throw; -        } +        boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); +        op_queue<operation> ops; +        ops.push(completed_ops_); +        timer_queues_.get_ready_timers(ops); +        post_deferred_completions(ops);        }        if (!ok && overlapped == 0) @@ -522,11 +522,9 @@ private:        }        else if (overlapped)        { -        // We may have been passed a last_error value in the completion_key. -        if (last_error == 0) -        { -          last_error = completion_key; -        } +        operation* op = static_cast<operation*>(overlapped); +        boost::system::error_code result_ec(last_error, +            boost::asio::error::get_system_category());          // Transfer responsibility for dispatching timers to another thread.          if (dispatching_timers && ::InterlockedCompareExchange( @@ -536,14 +534,35 @@ private:                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); +        // We may have been passed the last_error and bytes_transferred in the +        // OVERLAPPED structure itself. +        if (completion_key == overlapped_contains_result) +        { +          result_ec = boost::system::error_code(static_cast<int>(op->Offset), +              *reinterpret_cast<boost::system::error_category*>(op->Internal)); +          bytes_transferred = op->OffsetHigh; +        } -        // Dispatch the operation. -        operation* op = static_cast<operation*>(overlapped); -        if (op->on_completion(last_error, bytes_transferred)) +        // Otherwise ensure any result has been saved into the OVERLAPPED +        // structure. +        else          { +          op->Internal = reinterpret_cast<ulong_ptr_t>(&result_ec.category()); +          op->Offset = result_ec.value(); +          op->OffsetHigh = bytes_transferred; +        } + +        // Dispatch the operation only if ready. The operation may not be ready +        // if the initiating function (e.g. a call to WSARecv) has not yet +        // returned. This is because the initiating function still wants access +        // to the operation's OVERLAPPED structure. +        if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1) +        { +          // Ensure the count of outstanding work is decremented on block exit. +          work_finished_on_block_exit on_exit = { this }; +          (void)on_exit; + +          op->complete(*this, result_ec, bytes_transferred);            ec = boost::system::error_code();            return 1;          } @@ -588,126 +607,23 @@ 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; -    } +    return timer_queues_.wait_duration_msec(max_timeout);    } -  struct auto_work +  // Helper class to call work_finished() on block exit. +  struct work_finished_on_block_exit    { -    auto_work(win_iocp_io_service& io_service) -      : io_service_(io_service) +    ~work_finished_on_block_exit()      { -      io_service_.work_started(); +      io_service_->work_finished();      } -    ~auto_work() -    { -      io_service_.work_finished(); -    } - -  private: -    win_iocp_io_service& io_service_; -  }; - -  template <typename Handler> -  struct handler_operation -    : public operation -  { -    handler_operation(win_iocp_io_service& io_service, -        Handler handler) -      : operation(io_service, &handler_operation<Handler>::do_completion_impl, -          &handler_operation<Handler>::destroy_impl), -        io_service_(io_service), -        handler_(handler) -    { -      io_service_.work_started(); -    } - -    ~handler_operation() -    { -      io_service_.work_finished(); -    } - -  private: -    // Prevent copying and assignment. -    handler_operation(const handler_operation&); -    void operator=(const handler_operation&); -     -    static void do_completion_impl(operation* op, DWORD, size_t) -    { -      // Take ownership of the operation object. -      typedef handler_operation<Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Make the upcall. -      boost_asio_handler_invoke_helpers::invoke(handler, handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef handler_operation<Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset(); -    } - -    win_iocp_io_service& io_service_; -    Handler handler_; +    win_iocp_io_service* io_service_;    };    // The IO completion port used for queueing operations. @@ -721,10 +637,6 @@ private:    // The count of unfinished work.    long outstanding_work_; -  // The count of unfinished operations. -  long outstanding_operations_; -  friend class operation; -    // Flag to indicate whether the event loop has been stopped.    long stopped_; @@ -742,7 +654,12 @@ private:      // Completion key value to indicate that responsibility for dispatching      // timers should be stolen from another thread. -    steal_timer_dispatching = 2 +    steal_timer_dispatching = 2, + +    // Completion key value to indicate that an operation has posted with the +    // original last_error and bytes_transferred values stored in the fields of +    // the OVERLAPPED structure. +    overlapped_contains_result = 3    };    // The thread that's currently in charge of dispatching timers. @@ -755,12 +672,10 @@ private:    bool timer_interrupt_issued_;    // The timer queues. -  std::vector<timer_queue_base*> timer_queues_; +  timer_queue_set 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_; +  // The operations that are ready to dispatch. +  op_queue<operation> completed_ops_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_operation.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_operation.hpp new file mode 100644 index 0000000..d7d5723 --- /dev/null +++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_operation.hpp @@ -0,0 +1,91 @@ +// +// win_iocp_operation.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_OPERATION_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_OPERATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +#include <boost/asio/detail/win_iocp_io_service_fwd.hpp> + +#if defined(BOOST_ASIO_HAS_IOCP) + +#include <boost/asio/detail/op_queue.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// Base class for all operations. A function pointer is used instead of virtual +// functions to avoid the associated overhead. +class win_iocp_operation +  : public OVERLAPPED +{ +public: +  void complete(win_iocp_io_service& owner, +      const boost::system::error_code& ec = boost::system::error_code(), +      std::size_t bytes_transferred = 0) +  { +    func_(&owner, this, ec, bytes_transferred); +  } + +  void destroy() +  { +    func_(0, this, boost::system::error_code(), 0); +  } + +protected: +  typedef void (*func_type)(win_iocp_io_service*, +      win_iocp_operation*, boost::system::error_code, std::size_t); + +  win_iocp_operation(func_type func) +    : next_(0), +      func_(func) +  { +    reset(); +  } + +  // Prevents deletion through this type. +  ~win_iocp_operation() +  { +  } + +  void reset() +  { +    Internal = 0; +    InternalHigh = 0; +    Offset = 0; +    OffsetHigh = 0; +    hEvent = 0; +    ready_ = 0; +  } + +private: +  friend class op_queue_access; +  friend class win_iocp_io_service; +  win_iocp_operation* next_; +  func_type func_; +  long ready_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include <boost/system/error_code.hpp> +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_OPERATION_HPP diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp index bb64014..082a5b1 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp @@ -21,8 +21,10 @@  #if defined(BOOST_ASIO_HAS_IOCP) +#include <boost/asio/detail/fenced_block.hpp>  #include <boost/asio/detail/noncopyable.hpp>  #include <boost/asio/detail/win_iocp_io_service.hpp> +#include <boost/asio/detail/win_iocp_operation.hpp>  namespace boost {  namespace asio { @@ -35,7 +37,8 @@ class win_iocp_overlapped_ptr  public:    // Construct an empty win_iocp_overlapped_ptr.    win_iocp_overlapped_ptr() -    : ptr_(0) +    : ptr_(0), +      iocp_service_(0)    {    } @@ -43,7 +46,8 @@ public:    template <typename Handler>    explicit win_iocp_overlapped_ptr(        boost::asio::io_service& io_service, Handler handler) -    : ptr_(0) +    : ptr_(0), +      iocp_service_(0)    {      this->reset(io_service, handler);    } @@ -61,6 +65,8 @@ public:      {        ptr_->destroy();        ptr_ = 0; +      iocp_service_->work_finished(); +      iocp_service_ = 0;      }    } @@ -69,12 +75,14 @@ public:    template <typename Handler>    void reset(boost::asio::io_service& io_service, Handler handler)    { -    typedef overlapped_operation<Handler> value_type; +    typedef overlapped_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, io_service.impl_, handler); +    handler_ptr<alloc_traits> ptr(raw_ptr, handler); +    io_service.impl_.work_started();      reset();      ptr_ = ptr.release(); +    iocp_service_ = &io_service.impl_;    }    // Get the contained OVERLAPPED object. @@ -93,10 +101,11 @@ public:    OVERLAPPED* release()    {      if (ptr_) -      ptr_->on_pending(); +      iocp_service_->on_pending(ptr_);      OVERLAPPED* tmp = ptr_;      ptr_ = 0; +    iocp_service_ = 0;      return tmp;    } @@ -106,99 +115,54 @@ public:    {      if (ptr_)      { -      ptr_->ec_ = ec; -      ptr_->on_immediate_completion(0, static_cast<DWORD>(bytes_transferred)); +      iocp_service_->on_completion(ptr_, ec, +          static_cast<DWORD>(bytes_transferred));        ptr_ = 0; +      iocp_service_ = 0;      }    }  private: -  struct overlapped_operation_base -    : public win_iocp_io_service::operation -  { -    overlapped_operation_base(win_iocp_io_service& io_service, -        invoke_func_type invoke_func, destroy_func_type destroy_func) -      : win_iocp_io_service::operation(io_service, invoke_func, destroy_func), -        io_service_(io_service) -    { -      io_service_.work_started(); -    } - -    ~overlapped_operation_base() -    { -      io_service_.work_finished(); -    } - -    win_iocp_io_service& io_service_; -    boost::system::error_code ec_; -  }; -    template <typename Handler> -  struct overlapped_operation -    : public overlapped_operation_base +  struct overlapped_op : public win_iocp_operation    { -    overlapped_operation(win_iocp_io_service& io_service, -        Handler handler) -      : overlapped_operation_base(io_service, -          &overlapped_operation<Handler>::do_completion_impl, -          &overlapped_operation<Handler>::destroy_impl), +    overlapped_op(Handler handler) +      : win_iocp_operation(&overlapped_op::do_complete),          handler_(handler)      {      } -  private: -    // Prevent copying and assignment. -    overlapped_operation(const overlapped_operation&); -    void operator=(const overlapped_operation&); -     -    static void do_completion_impl(win_iocp_io_service::operation* op, -        DWORD last_error, size_t bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t bytes_transferred)      {        // Take ownership of the operation object. -      typedef overlapped_operation<Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // Make a copy of the handler and error_code so that the memory can be -      // deallocated before the upcall is made. -      Handler handler(handler_op->handler_); -      boost::system::error_code ec(handler_op->ec_); -      if (last_error) -        ec = boost::system::error_code(last_error, -            boost::asio::error::get_system_category()); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Make the upcall. -      boost_asio_handler_invoke_helpers::invoke( -          bind_handler(handler, ec, bytes_transferred), handler); -    } - -    static void destroy_impl(win_iocp_io_service::operation* op) -    { -      // Take ownership of the operation object. -      typedef overlapped_operation<Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset(); +      overlapped_op* o(static_cast<overlapped_op*>(base)); +      typedef handler_alloc_traits<Handler, overlapped_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); + +      // Make the upcall if required. +      if (owner) +      { +        // 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, std::size_t> +          handler(o->handler_, ec, bytes_transferred); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      } +  private:      Handler handler_;    }; -  overlapped_operation_base* ptr_; +  win_iocp_operation* ptr_; +  win_iocp_io_service* iocp_service_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_serial_port_service.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_serial_port_service.hpp index 4d6d2e9..288287c 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_iocp_serial_port_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_serial_port_service.hpp @@ -37,7 +37,6 @@ namespace detail {  // Extend win_iocp_handle_service to provide serial port support.  class win_iocp_serial_port_service -  : public boost::asio::detail::service_base<win_iocp_serial_port_service>  {  public:    // The native type of a stream handle. @@ -47,10 +46,7 @@ public:    typedef win_iocp_handle_service::implementation_type implementation_type;    win_iocp_serial_port_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        win_iocp_serial_port_service>(io_service), -      handle_service_( -          boost::asio::use_service<win_iocp_handle_service>(io_service)) +    : handle_service_(io_service)    {    } @@ -279,8 +275,8 @@ public:    }  private: -  // The handle service used for initiating asynchronous operations. -  win_iocp_handle_service& handle_service_; +  // The implementation used for initiating asynchronous operations. +  win_iocp_handle_service handle_service_;  };  } // namespace detail diff --git a/3rdParty/Boost/src/boost/asio/detail/win_iocp_socket_service.hpp b/3rdParty/Boost/src/boost/asio/detail/win_iocp_socket_service.hpp index e0c0806..5d545a8 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_iocp_socket_service.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_iocp_socket_service.hpp @@ -28,15 +28,19 @@  #include <boost/weak_ptr.hpp>  #include <boost/asio/detail/pop_options.hpp> -#include <boost/asio/buffer.hpp>  #include <boost/asio/error.hpp>  #include <boost/asio/io_service.hpp>  #include <boost/asio/socket_base.hpp>  #include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/buffer_sequence_adapter.hpp> +#include <boost/asio/detail/fenced_block.hpp>  #include <boost/asio/detail/handler_alloc_helpers.hpp>  #include <boost/asio/detail/handler_invoke_helpers.hpp>  #include <boost/asio/detail/mutex.hpp> -#include <boost/asio/detail/select_reactor.hpp> +#include <boost/asio/detail/null_buffers_op.hpp> +#include <boost/asio/detail/operation.hpp> +#include <boost/asio/detail/reactor.hpp> +#include <boost/asio/detail/reactor_op.hpp>  #include <boost/asio/detail/socket_holder.hpp>  #include <boost/asio/detail/socket_ops.hpp>  #include <boost/asio/detail/socket_types.hpp> @@ -48,7 +52,6 @@ namespace detail {  template <typename Protocol>  class win_iocp_socket_service -  : public boost::asio::detail::service_base<win_iocp_socket_service<Protocol> >  {  public:    // The protocol type. @@ -57,9 +60,6 @@ public:    // The endpoint type.    typedef typename Protocol::endpoint endpoint_type; -  // Base class for all operations. -  typedef win_iocp_io_service::operation operation; -    struct noop_deleter { void operator()(void*) {} };    typedef boost::shared_ptr<void> shared_cancel_token_type;    typedef boost::weak_ptr<void> weak_cancel_token_type; @@ -114,9 +114,6 @@ public:      endpoint_type remote_endpoint_;    }; -  // The type of the reactor used for connect operations. -  typedef detail::select_reactor<true> reactor_type; -    // The implementation type of the socket.    class implementation_type    { @@ -161,7 +158,7 @@ public:      protocol_type protocol_;      // Per-descriptor data used by the reactor. -    reactor_type::per_descriptor_data reactor_data_; +    reactor::per_descriptor_data reactor_data_;  #if defined(BOOST_ASIO_ENABLE_CANCELIO)      // The ID of the thread from which it is safe to cancel asynchronous @@ -176,14 +173,10 @@ public:      implementation_type* prev_;    }; -  // The maximum number of buffers to support in a single operation. -  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; -    // Constructor.    win_iocp_socket_service(boost::asio::io_service& io_service) -    : boost::asio::detail::service_base< -        win_iocp_socket_service<Protocol> >(io_service), -      iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)), +    : io_service_(io_service), +      iocp_service_(use_service<win_iocp_io_service>(io_service)),        reactor_(0),        mutex_(),        impl_list_(0) @@ -304,11 +297,11 @@ public:        // Check if the reactor was created, in which case we need to close the        // socket on the reactor as well to cancel any operations that might be        // running there. -      reactor_type* reactor = static_cast<reactor_type*>( +      reactor* r = static_cast<reactor*>(              interlocked_compare_exchange_pointer(                reinterpret_cast<void**>(&reactor_), 0, 0)); -      if (reactor) -        reactor->close_descriptor(impl.socket_, impl.reactor_data_); +      if (r) +        r->close_descriptor(impl.socket_, impl.reactor_data_);        if (socket_ops::close(impl.socket_, ec) == socket_error_retval)          return ec; @@ -665,23 +658,11 @@ public:        return 0;      } -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::const_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = const_cast<char*>( -          boost::asio::buffer_cast<const char*>(buffer)); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } +    buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence> bufs(buffers);      // A request to receive 0 bytes on a stream socket is a no-op. -    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) +    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())      {        ec = boost::system::error_code();        return 0; @@ -689,8 +670,8 @@ public:      // Send the data.      DWORD bytes_transferred = 0; -    int result = ::WSASend(impl.socket_, bufs, -        i, &bytes_transferred, flags, 0, 0); +    int result = ::WSASend(impl.socket_, bufs.buffers(), +        bufs.count(), &bytes_transferred, flags, 0, 0);      if (result != 0)      {        DWORD last_error = ::WSAGetLastError(); @@ -724,94 +705,63 @@ public:    }    template <typename ConstBufferSequence, typename Handler> -  class send_operation -    : public operation +  class send_op : public operation    {    public: -    send_operation(win_iocp_io_service& io_service, -        weak_cancel_token_type cancel_token, +    send_op(weak_cancel_token_type cancel_token,          const ConstBufferSequence& buffers, Handler handler) -      : operation(io_service, -          &send_operation<ConstBufferSequence, Handler>::do_completion_impl, -          &send_operation<ConstBufferSequence, Handler>::destroy_impl), -        work_(io_service.get_io_service()), +      : operation(&send_op::do_complete),          cancel_token_(cancel_token),          buffers_(buffers),          handler_(handler)      {      } -  private: -    static void do_completion_impl(operation* op, -        DWORD last_error, size_t bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t bytes_transferred)      {        // Take ownership of the operation object. -      typedef send_operation<ConstBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +      send_op* o(static_cast<send_op*>(base)); +      typedef handler_alloc_traits<Handler, send_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Check whether buffers are still valid. -      typename ConstBufferSequence::const_iterator iter -        = handler_op->buffers_.begin(); -      typename ConstBufferSequence::const_iterator end -        = handler_op->buffers_.end(); -      while (iter != end) +      // Make the upcall if required. +      if (owner)        { -        boost::asio::const_buffer buffer(*iter); -        boost::asio::buffer_cast<const char*>(buffer); -        ++iter; -      } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +        // Check whether buffers are still valid. +        buffer_sequence_adapter<boost::asio::const_buffer, +            ConstBufferSequence>::validate(o->buffers_);  #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Map non-portable errors to their portable counterparts. -      boost::system::error_code ec(last_error, -          boost::asio::error::get_system_category()); -      if (ec.value() == ERROR_NETNAME_DELETED) -      { -        if (handler_op->cancel_token_.expired()) -          ec = boost::asio::error::operation_aborted; -        else -          ec = boost::asio::error::connection_reset; -      } -      else if (ec.value() == ERROR_PORT_UNREACHABLE) -      { -        ec = boost::asio::error::connection_refused; -      } - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Call the handler. -      boost_asio_handler_invoke_helpers::invoke( -          detail::bind_handler(handler, ec, bytes_transferred), handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef send_operation<ConstBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; +        // Map non-portable errors to their portable counterparts. +        if (ec.value() == ERROR_NETNAME_DELETED) +        { +          if (o->cancel_token_.expired()) +            ec = boost::asio::error::operation_aborted; +          else +            ec = boost::asio::error::connection_reset; +        } +        else if (ec.value() == ERROR_PORT_UNREACHABLE) +        { +          ec = boost::asio::error::connection_refused; +        } -      // Free the memory associated with the handler. -      ptr.reset(); +        // 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, std::size_t> +          handler(o->handler_, ec, bytes_transferred); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      } -    boost::asio::io_service::work work_; +  private:      weak_cancel_token_type cancel_token_;      ConstBufferSequence buffers_;      Handler handler_; @@ -823,127 +773,34 @@ public:    void async_send(implementation_type& impl, const ConstBufferSequence& buffers,        socket_base::message_flags flags, Handler handler)    { -#if defined(BOOST_ASIO_ENABLE_CANCELIO) -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) -      // Allocate and construct an operation to wrap the handler. -    typedef send_operation<ConstBufferSequence, Handler> value_type; +    typedef send_op<ConstBufferSequence, 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, iocp_service_, +    handler_ptr<alloc_traits> ptr(raw_ptr,          impl.cancel_token_, buffers, handler); -    if (!is_open(impl)) -    { -      ptr.get()->on_immediate_completion(WSAEBADF, 0); -      ptr.release(); -      return; -    } - -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::const_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = const_cast<char*>( -          boost::asio::buffer_cast<const char*>(buffer)); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } - -    // A request to receive 0 bytes on a stream socket is a no-op. -    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) -    { -      ptr.get()->on_immediate_completion(0, 0); -      ptr.release(); -      return; -    } - -    // Send the data. -    DWORD bytes_transferred = 0; -    int result = ::WSASend(impl.socket_, bufs, i, -        &bytes_transferred, flags, ptr.get(), 0); -    DWORD last_error = ::WSAGetLastError(); +    buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence> bufs(buffers); -    // Check if the operation completed immediately. -    if (result != 0 && last_error != WSA_IO_PENDING) -    { -      ptr.get()->on_immediate_completion(last_error, bytes_transferred); -      ptr.release(); -    } -    else -    { -      ptr.get()->on_pending(); -      ptr.release(); -    } +    start_send_op(impl, bufs.buffers(), bufs.count(), flags, +        impl.protocol_.type() == SOCK_STREAM && bufs.all_empty(), ptr.get()); +    ptr.release();    } -  template <typename Handler> -  class null_buffers_operation -  { -  public: -    null_buffers_operation(boost::asio::io_service& io_service, Handler handler) -      : work_(io_service), -        handler_(handler) -    { -    } - -    bool perform(boost::system::error_code&, -        std::size_t& bytes_transferred) -    { -      bytes_transferred = 0; -      return true; -    } - -    void complete(const boost::system::error_code& ec, -        std::size_t bytes_transferred) -    { -      work_.get_io_service().post(bind_handler( -            handler_, ec, bytes_transferred)); -    } - -  private: -    boost::asio::io_service::work work_; -    Handler handler_; -  }; -    // Start an asynchronous wait until data can be sent without blocking.    template <typename Handler>    void async_send(implementation_type& impl, const null_buffers&,        socket_base::message_flags, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      // Check if the reactor was already obtained from the io_service. -      reactor_type* reactor = static_cast<reactor_type*>( -            interlocked_compare_exchange_pointer( -              reinterpret_cast<void**>(&reactor_), 0, 0)); -      if (!reactor) -      { -        reactor = &(boost::asio::use_service<reactor_type>( -              this->get_io_service())); -        interlocked_exchange_pointer( -            reinterpret_cast<void**>(&reactor_), reactor); -      } +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); -      reactor->start_write_op(impl.socket_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler), -          false); -    } +    start_reactor_op(impl, reactor::write_op, ptr.get()); +    ptr.release();    }    // Send a datagram to the specified endpoint. Returns the number of bytes @@ -959,23 +816,14 @@ public:        return 0;      } -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::const_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = const_cast<char*>( -          boost::asio::buffer_cast<const char*>(buffer)); -    } +    buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence> bufs(buffers);      // Send the data.      DWORD bytes_transferred = 0; -    int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, -        flags, destination.data(), static_cast<int>(destination.size()), 0, 0); +    int result = ::WSASendTo(impl.socket_, bufs.buffers(), bufs.count(), +        &bytes_transferred, flags, destination.data(), +        static_cast<int>(destination.size()), 0, 0);      if (result != 0)      {        DWORD last_error = ::WSAGetLastError(); @@ -1008,85 +856,57 @@ public:    }    template <typename ConstBufferSequence, typename Handler> -  class send_to_operation -    : public operation +  class send_to_op : public operation    {    public: -    send_to_operation(win_iocp_io_service& io_service, +    send_to_op(weak_cancel_token_type cancel_token,          const ConstBufferSequence& buffers, Handler handler) -      : operation(io_service, -          &send_to_operation<ConstBufferSequence, Handler>::do_completion_impl, -          &send_to_operation<ConstBufferSequence, Handler>::destroy_impl), -        work_(io_service.get_io_service()), +      : operation(&send_to_op::do_complete), +        cancel_token_(cancel_token),          buffers_(buffers),          handler_(handler)      {      } -  private: -    static void do_completion_impl(operation* op, -        DWORD last_error, size_t bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t bytes_transferred)      {        // Take ownership of the operation object. -      typedef send_to_operation<ConstBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +      send_to_op* o(static_cast<send_to_op*>(base)); +      typedef handler_alloc_traits<Handler, send_to_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Check whether buffers are still valid. -      typename ConstBufferSequence::const_iterator iter -        = handler_op->buffers_.begin(); -      typename ConstBufferSequence::const_iterator end -        = handler_op->buffers_.end(); -      while (iter != end) +      // Make the upcall if required. +      if (owner)        { -        boost::asio::const_buffer buffer(*iter); -        boost::asio::buffer_cast<const char*>(buffer); -        ++iter; -      } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +        // Check whether buffers are still valid. +        buffer_sequence_adapter<boost::asio::const_buffer, +            ConstBufferSequence>::validate(o->buffers_);  #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Map non-portable errors to their portable counterparts. -      boost::system::error_code ec(last_error, -          boost::asio::error::get_system_category()); -      if (ec.value() == ERROR_PORT_UNREACHABLE) -      { -        ec = boost::asio::error::connection_refused; -      } - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Call the handler. -      boost_asio_handler_invoke_helpers::invoke( -          detail::bind_handler(handler, ec, bytes_transferred), handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef send_to_operation<ConstBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; +        // Map non-portable errors to their portable counterparts. +        if (ec.value() == ERROR_PORT_UNREACHABLE) +        { +          ec = boost::asio::error::connection_refused; +        } -      // Free the memory associated with the handler. -      ptr.reset(); +        // 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, std::size_t> +          handler(o->handler_, ec, bytes_transferred); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      } -    boost::asio::io_service::work work_; +  private: +    weak_cancel_token_type cancel_token_;      ConstBufferSequence buffers_;      Handler handler_;    }; @@ -1098,57 +918,19 @@ public:        const ConstBufferSequence& buffers, const endpoint_type& destination,        socket_base::message_flags flags, Handler handler)    { -#if defined(BOOST_ASIO_ENABLE_CANCELIO) -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) -      // Allocate and construct an operation to wrap the handler. -    typedef send_to_operation<ConstBufferSequence, Handler> value_type; +    typedef send_to_op<ConstBufferSequence, 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, iocp_service_, buffers, handler); - -    if (!is_open(impl)) -    { -      ptr.get()->on_immediate_completion(WSAEBADF, 0); -      ptr.release(); -      return; -    } - -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename ConstBufferSequence::const_iterator iter = buffers.begin(); -    typename ConstBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::const_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = const_cast<char*>( -          boost::asio::buffer_cast<const char*>(buffer)); -    } +    handler_ptr<alloc_traits> ptr(raw_ptr, +        impl.cancel_token_, buffers, handler); -    // Send the data. -    DWORD bytes_transferred = 0; -    int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, flags, -        destination.data(), static_cast<int>(destination.size()), ptr.get(), 0); -    DWORD last_error = ::WSAGetLastError(); +    buffer_sequence_adapter<boost::asio::const_buffer, +        ConstBufferSequence> bufs(buffers); -    // Check if the operation completed immediately. -    if (result != 0 && last_error != WSA_IO_PENDING) -    { -      ptr.get()->on_immediate_completion(last_error, bytes_transferred); -      ptr.release(); -    } -    else -    { -      ptr.get()->on_pending(); -      ptr.release(); -    } +    start_send_to_op(impl, bufs.buffers(), +        bufs.count(), destination, flags, ptr.get()); +    ptr.release();    }    // Start an asynchronous wait until data can be sent without blocking. @@ -1156,29 +938,14 @@ public:    void async_send_to(implementation_type& impl, const null_buffers&,        socket_base::message_flags, const endpoint_type&, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      // Check if the reactor was already obtained from the io_service. -      reactor_type* reactor = static_cast<reactor_type*>( -            interlocked_compare_exchange_pointer( -              reinterpret_cast<void**>(&reactor_), 0, 0)); -      if (!reactor) -      { -        reactor = &(boost::asio::use_service<reactor_type>( -              this->get_io_service())); -        interlocked_exchange_pointer( -            reinterpret_cast<void**>(&reactor_), reactor); -      } +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); -      reactor->start_write_op(impl.socket_, impl.reactor_data_, -          null_buffers_operation<Handler>(this->get_io_service(), handler), -          false); -    } +    start_reactor_op(impl, reactor::write_op, ptr.get()); +    ptr.release();    }    // Receive some data from the peer. Returns the number of bytes received. @@ -1193,22 +960,11 @@ public:        return 0;      } -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::mutable_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = boost::asio::buffer_cast<char*>(buffer); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } +    buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence> bufs(buffers);      // A request to receive 0 bytes on a stream socket is a no-op. -    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) +    if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())      {        ec = boost::system::error_code();        return 0; @@ -1217,8 +973,8 @@ public:      // Receive some data.      DWORD bytes_transferred = 0;      DWORD recv_flags = flags; -    int result = ::WSARecv(impl.socket_, bufs, i, -        &bytes_transferred, &recv_flags, 0, 0); +    int result = ::WSARecv(impl.socket_, bufs.buffers(), +        bufs.count(), &bytes_transferred, &recv_flags, 0, 0);      if (result != 0)      {        DWORD last_error = ::WSAGetLastError(); @@ -1257,106 +1013,75 @@ public:    }    template <typename MutableBufferSequence, typename Handler> -  class receive_operation -    : public operation +  class receive_op : public operation    {    public: -    receive_operation(int protocol_type, win_iocp_io_service& io_service, -        weak_cancel_token_type cancel_token, +    receive_op(int protocol_type, weak_cancel_token_type cancel_token,          const MutableBufferSequence& buffers, Handler handler) -      : operation(io_service, -          &receive_operation< -            MutableBufferSequence, Handler>::do_completion_impl, -          &receive_operation< -            MutableBufferSequence, Handler>::destroy_impl), +      : operation(&receive_op::do_complete),          protocol_type_(protocol_type), -        work_(io_service.get_io_service()),          cancel_token_(cancel_token),          buffers_(buffers),          handler_(handler)      {      } -  private: -    static void do_completion_impl(operation* op, -        DWORD last_error, size_t bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t bytes_transferred)      {        // Take ownership of the operation object. -      typedef receive_operation<MutableBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +      receive_op* o(static_cast<receive_op*>(base)); +      typedef handler_alloc_traits<Handler, receive_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Check whether buffers are still valid. -      typename MutableBufferSequence::const_iterator iter -        = handler_op->buffers_.begin(); -      typename MutableBufferSequence::const_iterator end -        = handler_op->buffers_.end(); -      while (iter != end) +      // Make the upcall if required. +      if (owner)        { -        boost::asio::mutable_buffer buffer(*iter); -        boost::asio::buffer_cast<char*>(buffer); -        ++iter; -      } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +        // Check whether buffers are still valid. +        buffer_sequence_adapter<boost::asio::mutable_buffer, +            MutableBufferSequence>::validate(o->buffers_);  #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Map non-portable errors to their portable counterparts. -      boost::system::error_code ec(last_error, -          boost::asio::error::get_system_category()); -      if (ec.value() == ERROR_NETNAME_DELETED) -      { -        if (handler_op->cancel_token_.expired()) -          ec = boost::asio::error::operation_aborted; -        else -          ec = boost::asio::error::connection_reset; -      } -      else if (ec.value() == ERROR_PORT_UNREACHABLE) -      { -        ec = boost::asio::error::connection_refused; -      } - -      // Check for connection closed. -      else if (!ec && bytes_transferred == 0 -          && handler_op->protocol_type_ == SOCK_STREAM -          && !boost::is_same<MutableBufferSequence, null_buffers>::value) -      { -        ec = boost::asio::error::eof; -      } - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Call the handler. -      boost_asio_handler_invoke_helpers::invoke( -          detail::bind_handler(handler, ec, bytes_transferred), handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef receive_operation<MutableBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +        // Map non-portable errors to their portable counterparts. +        if (ec.value() == ERROR_NETNAME_DELETED) +        { +          if (o->cancel_token_.expired()) +            ec = boost::asio::error::operation_aborted; +          else +            ec = boost::asio::error::connection_reset; +        } +        else if (ec.value() == ERROR_PORT_UNREACHABLE) +        { +          ec = boost::asio::error::connection_refused; +        } -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; +        // Check for connection closed. +        else if (!ec && bytes_transferred == 0 +            && o->protocol_type_ == SOCK_STREAM +            && !buffer_sequence_adapter<boost::asio::mutable_buffer, +                MutableBufferSequence>::all_empty(o->buffers_) +            && !boost::is_same<MutableBufferSequence, null_buffers>::value) +        { +          ec = boost::asio::error::eof; +        } -      // Free the memory associated with the handler. -      ptr.reset(); +        // 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, std::size_t> +          handler(o->handler_, ec, bytes_transferred); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      } +  private:      int protocol_type_; -    boost::asio::io_service::work work_;      weak_cancel_token_type cancel_token_;      MutableBufferSequence buffers_;      Handler handler_; @@ -1369,67 +1094,20 @@ public:        const MutableBufferSequence& buffers,        socket_base::message_flags flags, Handler handler)    { -#if defined(BOOST_ASIO_ENABLE_CANCELIO) -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) -      // Allocate and construct an operation to wrap the handler. -    typedef receive_operation<MutableBufferSequence, Handler> value_type; +    typedef receive_op<MutableBufferSequence, Handler> value_type;      typedef handler_alloc_traits<Handler, value_type> alloc_traits;      raw_handler_ptr<alloc_traits> raw_ptr(handler);      int protocol_type = impl.protocol_.type();      handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type, -        iocp_service_, impl.cancel_token_, buffers, handler); - -    if (!is_open(impl)) -    { -      ptr.get()->on_immediate_completion(WSAEBADF, 0); -      ptr.release(); -      return; -    } - -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    size_t total_buffer_size = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::mutable_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = boost::asio::buffer_cast<char*>(buffer); -      total_buffer_size += boost::asio::buffer_size(buffer); -    } +        impl.cancel_token_, buffers, handler); -    // A request to receive 0 bytes on a stream socket is a no-op. -    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) -    { -      ptr.get()->on_immediate_completion(0, 0); -      ptr.release(); -      return; -    } +    buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence> bufs(buffers); -    // Receive some data. -    DWORD bytes_transferred = 0; -    DWORD recv_flags = flags; -    int result = ::WSARecv(impl.socket_, bufs, i, -        &bytes_transferred, &recv_flags, ptr.get(), 0); -    DWORD last_error = ::WSAGetLastError(); -    if (result != 0 && last_error != WSA_IO_PENDING) -    { -      ptr.get()->on_immediate_completion(last_error, bytes_transferred); -      ptr.release(); -    } -    else -    { -      ptr.get()->on_pending(); -      ptr.release(); -    } +    start_receive_op(impl, bufs.buffers(), bufs.count(), flags, +        protocol_type == SOCK_STREAM && bufs.all_empty(), ptr.get()); +    ptr.release();    }    // Wait until data can be received without blocking. @@ -1437,75 +1115,36 @@ public:    void async_receive(implementation_type& impl, const null_buffers& buffers,        socket_base::message_flags flags, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else if (impl.protocol_.type() == SOCK_STREAM) +    if (impl.protocol_.type() == SOCK_STREAM)      {        // For stream sockets on Windows, we may issue a 0-byte overlapped        // WSARecv to wait until there is data available on the socket. -#if defined(BOOST_ASIO_ENABLE_CANCELIO) -      // Update the ID of the thread from which cancellation is safe. -      if (impl.safe_cancellation_thread_id_ == 0) -        impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -      else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -        impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) -        // Allocate and construct an operation to wrap the handler. -      typedef receive_operation<null_buffers, Handler> value_type; +      typedef receive_op<null_buffers, Handler> value_type;        typedef handler_alloc_traits<Handler, value_type> alloc_traits;        raw_handler_ptr<alloc_traits> raw_ptr(handler);        int protocol_type = impl.protocol_.type();        handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type, -          iocp_service_, impl.cancel_token_, buffers, handler); +          impl.cancel_token_, buffers, handler); -      // Issue a receive operation with an empty buffer.        ::WSABUF buf = { 0, 0 }; -      DWORD bytes_transferred = 0; -      DWORD recv_flags = flags; -      int result = ::WSARecv(impl.socket_, &buf, 1, -          &bytes_transferred, &recv_flags, ptr.get(), 0); -      DWORD last_error = ::WSAGetLastError(); -      if (result != 0 && last_error != WSA_IO_PENDING) -      { -        ptr.get()->on_immediate_completion(last_error, bytes_transferred); -        ptr.release(); -      } -      else -      { -        ptr.get()->on_pending(); -        ptr.release(); -      } +      start_receive_op(impl, &buf, 1, flags, false, ptr.get()); +      ptr.release();      }      else      { -      // Check if the reactor was already obtained from the io_service. -      reactor_type* reactor = static_cast<reactor_type*>( -            interlocked_compare_exchange_pointer( -              reinterpret_cast<void**>(&reactor_), 0, 0)); -      if (!reactor) -      { -        reactor = &(boost::asio::use_service<reactor_type>( -              this->get_io_service())); -        interlocked_exchange_pointer( -            reinterpret_cast<void**>(&reactor_), reactor); -      } +      // Allocate and construct an operation to wrap the handler. +      typedef null_buffers_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, handler); -      if (flags & socket_base::message_out_of_band) -      { -        reactor->start_except_op(impl.socket_, impl.reactor_data_, -            null_buffers_operation<Handler>(this->get_io_service(), handler)); -      } -      else -      { -        reactor->start_read_op(impl.socket_, impl.reactor_data_, -            null_buffers_operation<Handler>(this->get_io_service(), handler), -            false); -      } +      start_reactor_op(impl, +          (flags & socket_base::message_out_of_band) +            ? reactor::except_op : reactor::read_op, +          ptr.get()); +      ptr.release();      }    } @@ -1523,24 +1162,16 @@ public:        return 0;      } -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::mutable_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = boost::asio::buffer_cast<char*>(buffer); -    } +    buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence> bufs(buffers);      // Receive some data.      DWORD bytes_transferred = 0;      DWORD recv_flags = flags;      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); +    int result = ::WSARecvFrom(impl.socket_, bufs.buffers(), +        bufs.count(), &bytes_transferred, &recv_flags, +        sender_endpoint.data(), &endpoint_size, 0, 0);      if (result != 0)      {        DWORD last_error = ::WSAGetLastError(); @@ -1583,22 +1214,15 @@ public:    }    template <typename MutableBufferSequence, typename Handler> -  class receive_from_operation -    : public operation +  class receive_from_op : public operation    {    public: -    receive_from_operation(int protocol_type, win_iocp_io_service& io_service, -        endpoint_type& endpoint, const MutableBufferSequence& buffers, -        Handler handler) -      : operation(io_service, -          &receive_from_operation< -            MutableBufferSequence, Handler>::do_completion_impl, -          &receive_from_operation< -            MutableBufferSequence, Handler>::destroy_impl), +    receive_from_op(int protocol_type, endpoint_type& endpoint, +        const MutableBufferSequence& buffers, Handler handler) +      : operation(&receive_from_op::do_complete),          protocol_type_(protocol_type),          endpoint_(endpoint),          endpoint_size_(static_cast<int>(endpoint.capacity())), -        work_(io_service.get_io_service()),          buffers_(buffers),          handler_(handler)      { @@ -1609,83 +1233,51 @@ public:        return endpoint_size_;      } -  private: -    static void do_completion_impl(operation* op, -        DWORD last_error, size_t bytes_transferred) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t bytes_transferred)      {        // Take ownership of the operation object. -      typedef receive_from_operation<MutableBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +      receive_from_op* o(static_cast<receive_from_op*>(base)); +      typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Check whether buffers are still valid. -      typename MutableBufferSequence::const_iterator iter -        = handler_op->buffers_.begin(); -      typename MutableBufferSequence::const_iterator end -        = handler_op->buffers_.end(); -      while (iter != end) +      // Make the upcall if required. +      if (owner)        { -        boost::asio::mutable_buffer buffer(*iter); -        boost::asio::buffer_cast<char*>(buffer); -        ++iter; -      } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +        // Check whether buffers are still valid. +        buffer_sequence_adapter<boost::asio::mutable_buffer, +            MutableBufferSequence>::validate(o->buffers_);  #endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -      // Map non-portable errors to their portable counterparts. -      boost::system::error_code ec(last_error, -          boost::asio::error::get_system_category()); -      if (ec.value() == ERROR_PORT_UNREACHABLE) -      { -        ec = boost::asio::error::connection_refused; -      } +        // Map non-portable errors to their portable counterparts. +        if (ec.value() == ERROR_PORT_UNREACHABLE) +        { +          ec = boost::asio::error::connection_refused; +        } -      // Check for connection closed. -      if (!ec && bytes_transferred == 0 -          && handler_op->protocol_type_ == SOCK_STREAM) -      { -        ec = boost::asio::error::eof; +        // Record the size of the endpoint returned by the operation. +        o->endpoint_.resize(o->endpoint_size_); + +        // 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, std::size_t> +          handler(o->handler_, ec, bytes_transferred); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler);        } - -      // Record the size of the endpoint returned by the operation. -      handler_op->endpoint_.resize(handler_op->endpoint_size_); - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Call the handler. -      boost_asio_handler_invoke_helpers::invoke( -          detail::bind_handler(handler, ec, bytes_transferred), handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef receive_from_operation<MutableBufferSequence, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset();      } +  private:      int protocol_type_;      endpoint_type& endpoint_;      int endpoint_size_; -    boost::asio::io_service::work work_; +    weak_cancel_token_type cancel_token_;      MutableBufferSequence buffers_;      Handler handler_;    }; @@ -1698,58 +1290,20 @@ public:        const MutableBufferSequence& buffers, endpoint_type& sender_endp,        socket_base::message_flags flags, Handler handler)    { -#if defined(BOOST_ASIO_ENABLE_CANCELIO) -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) -      // Allocate and construct an operation to wrap the handler. -    typedef receive_from_operation<MutableBufferSequence, Handler> value_type; +    typedef receive_from_op<MutableBufferSequence, Handler> value_type;      typedef handler_alloc_traits<Handler, value_type> alloc_traits;      raw_handler_ptr<alloc_traits> raw_ptr(handler);      int protocol_type = impl.protocol_.type(); -    handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type, -        iocp_service_, sender_endp, buffers, handler); - -    if (!is_open(impl)) -    { -      ptr.get()->on_immediate_completion(WSAEBADF, 0); -      ptr.release(); -      return; -    } +    handler_ptr<alloc_traits> ptr(raw_ptr, +        protocol_type, sender_endp, buffers, handler); -    // Copy buffers into WSABUF array. -    ::WSABUF bufs[max_buffers]; -    typename MutableBufferSequence::const_iterator iter = buffers.begin(); -    typename MutableBufferSequence::const_iterator end = buffers.end(); -    DWORD i = 0; -    for (; iter != end && i < max_buffers; ++iter, ++i) -    { -      boost::asio::mutable_buffer buffer(*iter); -      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer)); -      bufs[i].buf = boost::asio::buffer_cast<char*>(buffer); -    } +    buffer_sequence_adapter<boost::asio::mutable_buffer, +        MutableBufferSequence> bufs(buffers); -    // Receive some data. -    DWORD bytes_transferred = 0; -    DWORD recv_flags = flags; -    int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred, -        &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(), -        ptr.get(), 0); -    DWORD last_error = ::WSAGetLastError(); -    if (result != 0 && last_error != WSA_IO_PENDING) -    { -      ptr.get()->on_immediate_completion(last_error, bytes_transferred); -      ptr.release(); -    } -    else -    { -      ptr.get()->on_pending(); -      ptr.release(); -    } +    start_receive_from_op(impl, bufs.buffers(), bufs.count(), +        sender_endp, flags, &ptr.get()->endpoint_size(), ptr.get()); +    ptr.release();    }    // Wait until data can be received without blocking. @@ -1758,40 +1312,20 @@ public:        const null_buffers&, endpoint_type& sender_endpoint,        socket_base::message_flags flags, Handler handler)    { -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor, 0)); -    } -    else -    { -      // Check if the reactor was already obtained from the io_service. -      reactor_type* reactor = static_cast<reactor_type*>( -            interlocked_compare_exchange_pointer( -              reinterpret_cast<void**>(&reactor_), 0, 0)); -      if (!reactor) -      { -        reactor = &(boost::asio::use_service<reactor_type>( -              this->get_io_service())); -        interlocked_exchange_pointer( -            reinterpret_cast<void**>(&reactor_), reactor); -      } +    // Allocate and construct an operation to wrap the handler. +    typedef null_buffers_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, handler); -      // Reset endpoint since it can be given no sensible value at this time. -      sender_endpoint = endpoint_type(); +    // Reset endpoint since it can be given no sensible value at this time. +    sender_endpoint = endpoint_type(); -      if (flags & socket_base::message_out_of_band) -      { -        reactor->start_except_op(impl.socket_, impl.reactor_data_, -            null_buffers_operation<Handler>(this->get_io_service(), handler)); -      } -      else -      { -        reactor->start_read_op(impl.socket_, impl.reactor_data_, -            null_buffers_operation<Handler>(this->get_io_service(), handler), -            false); -      } -    } +    start_reactor_op(impl, +        (flags & socket_base::message_out_of_band) +          ? reactor::except_op : reactor::read_op, +        ptr.get()); +    ptr.release();    }    // Accept a new connection. @@ -1852,32 +1386,27 @@ public:    }    template <typename Socket, typename Handler> -  class accept_operation -    : public operation +  class accept_op : public operation    {    public: -    accept_operation(win_iocp_io_service& io_service, -        socket_type socket, socket_type new_socket, Socket& peer, -        const protocol_type& protocol, endpoint_type* peer_endpoint, -        bool enable_connection_aborted, Handler handler) -      : operation(io_service, -          &accept_operation<Socket, Handler>::do_completion_impl, -          &accept_operation<Socket, Handler>::destroy_impl), -        io_service_(io_service), +    accept_op(win_iocp_io_service& iocp_service, socket_type socket, +        Socket& peer, const protocol_type& protocol, +        endpoint_type* peer_endpoint, bool enable_connection_aborted, +        Handler handler) +      : operation(&accept_op::do_complete), +        iocp_service_(iocp_service),          socket_(socket), -        new_socket_(new_socket),          peer_(peer),          protocol_(protocol),          peer_endpoint_(peer_endpoint), -        work_(io_service.get_io_service()),          enable_connection_aborted_(enable_connection_aborted),          handler_(handler)      {      } -    socket_type new_socket() +    socket_holder& new_socket()      { -      return new_socket_.get(); +      return new_socket_;      }      void* output_buffer() @@ -1890,166 +1419,145 @@ public:        return sizeof(sockaddr_storage_type) + 16;      } -  private: -    static void do_completion_impl(operation* op, DWORD last_error, size_t) +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code ec, std::size_t /*bytes_transferred*/)      { -      // Take ownership of the operation object. -      typedef accept_operation<Socket, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); +      // Take ownership of the handler object. +      accept_op* o(static_cast<accept_op*>(base)); +      typedef handler_alloc_traits<Handler, accept_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); -      // Map Windows error ERROR_NETNAME_DELETED to connection_aborted. -      if (last_error == ERROR_NETNAME_DELETED) +      // Make the upcall if required. +      if (owner)        { -        last_error = WSAECONNABORTED; -      } +        // Map Windows error ERROR_NETNAME_DELETED to connection_aborted. +        if (ec.value() == ERROR_NETNAME_DELETED) +        { +          ec = boost::asio::error::connection_aborted; +        } -      // Restart the accept operation if we got the connection_aborted error -      // and the enable_connection_aborted socket option is not set. -      if (last_error == WSAECONNABORTED -          && !ptr.get()->enable_connection_aborted_) -      { -        // Reset OVERLAPPED structure. -        ptr.get()->reset(); - -        // Create a new socket for the next connection, since the AcceptEx call -        // fails with WSAEINVAL if we try to reuse the same socket. -        boost::system::error_code ec; -        ptr.get()->new_socket_.reset(); -        ptr.get()->new_socket_.reset(socket_ops::socket( -              ptr.get()->protocol_.family(), ptr.get()->protocol_.type(), -              ptr.get()->protocol_.protocol(), ec)); -        if (ptr.get()->new_socket() != invalid_socket) +        // Restart the accept operation if we got the connection_aborted error +        // and the enable_connection_aborted socket option is not set. +        if (ec == boost::asio::error::connection_aborted +            && !o->enable_connection_aborted_)          { -          // Accept a connection. -          DWORD bytes_read = 0; -          BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(), -              ptr.get()->output_buffer(), 0, ptr.get()->address_length(), -              ptr.get()->address_length(), &bytes_read, ptr.get()); -          last_error = ::WSAGetLastError(); - -          // Check if the operation completed immediately. -          if (!result && last_error != WSA_IO_PENDING) +          // Reset OVERLAPPED structure. +          o->reset(); + +          // Create a new socket for the next connection, since the AcceptEx +          // call fails with WSAEINVAL if we try to reuse the same socket. +          o->new_socket_.reset(); +          o->new_socket_.reset(socket_ops::socket(o->protocol_.family(), +                o->protocol_.type(), o->protocol_.protocol(), ec)); +          if (o->new_socket_.get() != invalid_socket)            { -            if (last_error == ERROR_NETNAME_DELETED -                || last_error == WSAECONNABORTED) +            // Accept a connection. +            DWORD bytes_read = 0; +            BOOL result = ::AcceptEx(o->socket_, o->new_socket_.get(), +                o->output_buffer(), 0, o->address_length(), +                o->address_length(), &bytes_read, o); +            DWORD last_error = ::WSAGetLastError(); +            ec = boost::system::error_code(last_error, +                boost::asio::error::get_system_category()); + +            // Check if the operation completed immediately. +            if (!result && last_error != WSA_IO_PENDING)              { -              // Post this handler so that operation will be restarted again. -              ptr.get()->on_immediate_completion(last_error, 0); -              ptr.release(); -              return; +              if (last_error == ERROR_NETNAME_DELETED +                  || last_error == WSAECONNABORTED) +              { +                // Post this handler so that operation will be restarted again. +                o->iocp_service_.work_started(); +                o->iocp_service_.on_completion(o, ec); +                ptr.release(); +                return; +              } +              else +              { +                // Operation already complete. Continue with rest of this +                // handler. +              }              }              else              { -              // Operation already complete. Continue with rest of this handler. +              // Asynchronous operation has been successfully restarted. +              o->iocp_service_.work_started(); +              o->iocp_service_.on_pending(o); +              ptr.release(); +              return;              }            } +        } + +        // Get the address of the peer. +        endpoint_type peer_endpoint; +        if (!ec) +        { +          LPSOCKADDR local_addr = 0; +          int local_addr_length = 0; +          LPSOCKADDR remote_addr = 0; +          int remote_addr_length = 0; +          GetAcceptExSockaddrs(o->output_buffer(), 0, o->address_length(), +              o->address_length(), &local_addr, &local_addr_length, +              &remote_addr, &remote_addr_length); +          if (static_cast<std::size_t>(remote_addr_length) +              > peer_endpoint.capacity()) +          { +            ec = boost::asio::error::invalid_argument; +          }            else            { -            // Asynchronous operation has been successfully restarted. -            ptr.get()->on_pending(); -            ptr.release(); -            return; +            using namespace std; // For memcpy. +            memcpy(peer_endpoint.data(), remote_addr, remote_addr_length); +            peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));            }          } -      } -      // Get the address of the peer. -      endpoint_type peer_endpoint; -      if (last_error == 0) -      { -        LPSOCKADDR local_addr = 0; -        int local_addr_length = 0; -        LPSOCKADDR remote_addr = 0; -        int remote_addr_length = 0; -        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 (static_cast<std::size_t>(remote_addr_length) -            > peer_endpoint.capacity()) -        { -          last_error = WSAEINVAL; -        } -        else +        // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname +        // and getpeername will work on the accepted socket. +        if (!ec)          { -          using namespace std; // For memcpy. -          memcpy(peer_endpoint.data(), remote_addr, remote_addr_length); -          peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length)); +          SOCKET update_ctx_param = o->socket_; +          socket_ops::setsockopt(o->new_socket_.get(), +                SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, +                &update_ctx_param, sizeof(SOCKET), ec);          } -      } -      // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname -      // and getpeername will work on the accepted socket. -      if (last_error == 0) -      { -        SOCKET update_ctx_param = handler_op->socket_; -        boost::system::error_code ec; -        if (socket_ops::setsockopt(handler_op->new_socket_.get(), -              SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, -              &update_ctx_param, sizeof(SOCKET), ec) != 0) +        // If the socket was successfully accepted, transfer ownership of the +        // socket to the peer object. +        if (!ec)          { -          last_error = ec.value(); +          o->peer_.assign(o->protocol_, +              native_type(o->new_socket_.get(), peer_endpoint), ec); +          if (!ec) +            o->new_socket_.release();          } -      } -      // If the socket was successfully accepted, transfer ownership of the -      // socket to the peer object. -      if (last_error == 0) -      { -        boost::system::error_code ec; -        handler_op->peer_.assign(handler_op->protocol_, -            native_type(handler_op->new_socket_.get(), peer_endpoint), ec); -        if (ec) -          last_error = ec.value(); -        else -          handler_op->new_socket_.release(); +        // Pass endpoint back to caller. +        if (o->peer_endpoint_) +          *o->peer_endpoint_ = peer_endpoint; + +        // 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::binder1<Handler, boost::system::error_code> +          handler(o->handler_, ec); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler);        } - -      // Pass endpoint back to caller. -      if (handler_op->peer_endpoint_) -        *handler_op->peer_endpoint_ = peer_endpoint; - -      // Make a copy of the handler so that the memory can be deallocated before -      // the upcall is made. -      Handler handler(handler_op->handler_); - -      // Free the memory associated with the handler. -      ptr.reset(); - -      // Call the handler. -      boost::system::error_code ec(last_error, -          boost::asio::error::get_system_category()); -      boost_asio_handler_invoke_helpers::invoke( -          detail::bind_handler(handler, ec), handler); -    } - -    static void destroy_impl(operation* op) -    { -      // Take ownership of the operation object. -      typedef accept_operation<Socket, Handler> op_type; -      op_type* handler_op(static_cast<op_type*>(op)); -      typedef handler_alloc_traits<Handler, op_type> alloc_traits; -      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op); - -      // 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. -      Handler handler(handler_op->handler_); -      (void)handler; - -      // Free the memory associated with the handler. -      ptr.reset();      } -    win_iocp_io_service& io_service_; +  private: +    win_iocp_io_service& iocp_service_;      socket_type socket_;      socket_holder new_socket_;      Socket& peer_;      protocol_type protocol_;      endpoint_type* peer_endpoint_; -    boost::asio::io_service::work work_;      unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];      bool enable_connection_aborted_;      Handler handler_; @@ -2061,86 +1569,18 @@ public:    void async_accept(implementation_type& impl, Socket& peer,        endpoint_type* peer_endpoint, Handler handler)    { -    // Check whether acceptor has been initialised. -    if (!is_open(impl)) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor)); -      return; -    } - -    // Check that peer socket has not already been opened. -    if (peer.is_open()) -    { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::already_open)); -      return; -    } - -#if defined(BOOST_ASIO_ENABLE_CANCELIO) -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) - -    // Create a new socket for the connection. -    boost::system::error_code ec; -    socket_holder sock(socket_ops::socket(impl.protocol_.family(), -          impl.protocol_.type(), impl.protocol_.protocol(), ec)); -    if (sock.get() == invalid_socket) -    { -      this->get_io_service().post(bind_handler(handler, ec)); -      return; -    } -      // Allocate and construct an operation to wrap the handler. -    typedef accept_operation<Socket, Handler> value_type; +    typedef accept_op<Socket, Handler> value_type;      typedef handler_alloc_traits<Handler, value_type> alloc_traits;      raw_handler_ptr<alloc_traits> raw_ptr(handler); -    socket_type new_socket = sock.get();      bool enable_connection_aborted =        (impl.flags_ & implementation_type::enable_connection_aborted); -    handler_ptr<alloc_traits> ptr(raw_ptr, -        iocp_service_, impl.socket_, new_socket, peer, impl.protocol_, -        peer_endpoint, enable_connection_aborted, handler); -    sock.release(); - -    // Accept a connection. -    DWORD bytes_read = 0; -    BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(), -        ptr.get()->output_buffer(), 0, ptr.get()->address_length(), -        ptr.get()->address_length(), &bytes_read, ptr.get()); -    DWORD last_error = ::WSAGetLastError(); - -    // Check if the operation completed immediately. -    if (!result && last_error != WSA_IO_PENDING) -    { -      if (!enable_connection_aborted -          && (last_error == ERROR_NETNAME_DELETED -            || last_error == WSAECONNABORTED)) -      { -        // Post handler so that operation will be restarted again. We do not -        // perform the AcceptEx again here to avoid the possibility of starving -        // other handlers. -        ptr.get()->on_immediate_completion(last_error, 0); -        ptr.release(); -      } -      else -      { -        boost::asio::io_service::work work(this->get_io_service()); -        ptr.reset(); -        boost::system::error_code ec(last_error, -            boost::asio::error::get_system_category()); -        iocp_service_.post(bind_handler(handler, ec)); -      } -    } -    else -    { -      ptr.get()->on_pending(); -      ptr.release(); -    } +    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, impl.socket_, peer, +        impl.protocol_, peer_endpoint, enable_connection_aborted, handler); + +    start_accept_op(impl, peer.is_open(), ptr.get()->new_socket(), +        ptr.get()->output_buffer(), ptr.get()->address_length(), ptr.get()); +    ptr.release();    }    // Connect the socket to the specified endpoint. @@ -2159,67 +1599,76 @@ public:      return ec;    } -  template <typename Handler> -  class connect_operation +  class connect_op_base : public reactor_op    {    public: -    connect_operation(socket_type socket, bool user_set_non_blocking, -        boost::asio::io_service& io_service, Handler handler) -      : socket_(socket), -        user_set_non_blocking_(user_set_non_blocking), -        io_service_(io_service), -        work_(io_service), -        handler_(handler) +    connect_op_base(socket_type socket, func_type complete_func) +      : reactor_op(&connect_op_base::do_perform, complete_func), +        socket_(socket)      {      } -    bool perform(boost::system::error_code& ec, -        std::size_t& bytes_transferred) +    static bool do_perform(reactor_op* base)      { -      bytes_transferred = 0; - -      // Check whether the operation was successful. -      if (ec) -        return true; +      connect_op_base* o(static_cast<connect_op_base*>(base));        // Get the error code from the connect operation.        int connect_error = 0;        size_t connect_error_len = sizeof(connect_error); -      if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, -            &connect_error, &connect_error_len, ec) == socket_error_retval) +      if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR, +            &connect_error, &connect_error_len, o->ec_) == socket_error_retval)          return true; -      // If connection failed then post the handler with the error code. +      // The connection failed so the handler will be posted with an error code.        if (connect_error)        { -        ec = boost::system::error_code(connect_error, +        o->ec_ = boost::system::error_code(connect_error,              boost::asio::error::get_system_category()); -        return true;        } -      // Revert socket to blocking mode unless the user requested otherwise. -      if (!user_set_non_blocking_) -      { -        ioctl_arg_type non_blocking = 0; -        if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec)) -          return true; -      } - -      // Post the result of the successful connection operation. -      ec = boost::system::error_code();        return true;      } -    void complete(const boost::system::error_code& ec, std::size_t) +  private: +    socket_type socket_; +  }; + +  template <typename Handler> +  class connect_op : public connect_op_base +  { +  public: +    connect_op(socket_type socket, Handler handler) +      : connect_op_base(socket, &connect_op::do_complete), +        handler_(handler)      { -      io_service_.post(bind_handler(handler_, ec)); +    } + +    static void do_complete(io_service_impl* owner, operation* base, +        boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/) +    { +      // Take ownership of the handler object. +      connect_op* o(static_cast<connect_op*>(base)); +      typedef handler_alloc_traits<Handler, connect_op> alloc_traits; +      handler_ptr<alloc_traits> ptr(o->handler_, o); + +      // Make the upcall if required. +      if (owner) +      { +        // 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::binder1<Handler, boost::system::error_code> +          handler(o->handler_, o->ec_); +        ptr.reset(); +        boost::asio::detail::fenced_block b; +        boost_asio_handler_invoke_helpers::invoke(handler, handler); +      }      }    private: -    socket_type socket_; -    bool user_set_non_blocking_; -    boost::asio::io_service& io_service_; -    boost::asio::io_service::work work_;      Handler handler_;    }; @@ -2228,86 +1677,216 @@ public:    void async_connect(implementation_type& impl,        const endpoint_type& peer_endpoint, Handler handler)    { +    // Allocate and construct an operation to wrap the handler. +    typedef connect_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.socket_, handler); + +    start_connect_op(impl, ptr.get(), peer_endpoint); +    ptr.release(); +  } + +private: +  // Helper function to start an asynchronous send operation. +  void start_send_op(implementation_type& impl, WSABUF* buffers, +      std::size_t buffer_count, socket_base::message_flags flags, +      bool noop, operation* op) +  { +    update_cancellation_thread_id(impl); +    iocp_service_.work_started(); + +    if (noop) +      iocp_service_.on_completion(op); +    else if (!is_open(impl)) +      iocp_service_.on_completion(op, boost::asio::error::bad_descriptor); +    else +    { +      DWORD bytes_transferred = 0; +      int result = ::WSASend(impl.socket_, buffers, +          buffer_count, &bytes_transferred, flags, op, 0); +      DWORD last_error = ::WSAGetLastError(); +      if (last_error == ERROR_PORT_UNREACHABLE) +        last_error = WSAECONNREFUSED; +      if (result != 0 && last_error != WSA_IO_PENDING) +        iocp_service_.on_completion(op, last_error, bytes_transferred); +      else +        iocp_service_.on_pending(op); +    } +  } + +  // Helper function to start an asynchronous send_to operation. +  void start_send_to_op(implementation_type& impl, WSABUF* buffers, +      std::size_t buffer_count, const endpoint_type& destination, +      socket_base::message_flags flags, operation* op) +  { +    update_cancellation_thread_id(impl); +    iocp_service_.work_started(); +      if (!is_open(impl)) +      iocp_service_.on_completion(op, boost::asio::error::bad_descriptor); +    else      { -      this->get_io_service().post(bind_handler(handler, -            boost::asio::error::bad_descriptor)); -      return; +      DWORD bytes_transferred = 0; +      int result = ::WSASendTo(impl.socket_, buffers, buffer_count, +          &bytes_transferred, flags, destination.data(), +          static_cast<int>(destination.size()), op, 0); +      DWORD last_error = ::WSAGetLastError(); +      if (last_error == ERROR_PORT_UNREACHABLE) +        last_error = WSAECONNREFUSED; +      if (result != 0 && last_error != WSA_IO_PENDING) +        iocp_service_.on_completion(op, last_error, bytes_transferred); +      else +        iocp_service_.on_pending(op);      } +  } -#if defined(BOOST_ASIO_ENABLE_CANCELIO) -    // Update the ID of the thread from which cancellation is safe. -    if (impl.safe_cancellation_thread_id_ == 0) -      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); -    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) -      impl.safe_cancellation_thread_id_ = ~DWORD(0); -#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) +  // Helper function to start an asynchronous receive operation. +  void start_receive_op(implementation_type& impl, WSABUF* buffers, +      std::size_t buffer_count, socket_base::message_flags flags, +      bool noop, operation* op) +  { +    update_cancellation_thread_id(impl); +    iocp_service_.work_started(); -    // Check if the reactor was already obtained from the io_service. -    reactor_type* reactor = static_cast<reactor_type*>( -          interlocked_compare_exchange_pointer( -            reinterpret_cast<void**>(&reactor_), 0, 0)); -    if (!reactor) +    if (noop) +      iocp_service_.on_completion(op); +    else if (!is_open(impl)) +      iocp_service_.on_completion(op, boost::asio::error::bad_descriptor); +    else      { -      reactor = &(boost::asio::use_service<reactor_type>( -            this->get_io_service())); -      interlocked_exchange_pointer( -          reinterpret_cast<void**>(&reactor_), reactor); +      DWORD bytes_transferred = 0; +      DWORD recv_flags = flags; +      int result = ::WSARecv(impl.socket_, buffers, buffer_count, +          &bytes_transferred, &recv_flags, op, 0); +      DWORD last_error = ::WSAGetLastError(); +      if (last_error == ERROR_NETNAME_DELETED) +        last_error = WSAECONNRESET; +      else if (last_error == ERROR_PORT_UNREACHABLE) +        last_error = WSAECONNREFUSED; +      if (result != 0 && last_error != WSA_IO_PENDING) +        iocp_service_.on_completion(op, last_error, bytes_transferred); +      else +        iocp_service_.on_pending(op);      } +  } -    // Mark the socket as non-blocking so that the connection will take place -    // asynchronously. -    ioctl_arg_type non_blocking = 1; -    boost::system::error_code ec; -    if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) +  // Helper function to start an asynchronous receive_from operation. +  void start_receive_from_op(implementation_type& impl, WSABUF* buffers, +      std::size_t buffer_count, endpoint_type& sender_endpoint, +      socket_base::message_flags flags, int* endpoint_size, operation* op) +  { +    update_cancellation_thread_id(impl); +    iocp_service_.work_started(); + +    if (!is_open(impl)) +      iocp_service_.on_completion(op, boost::asio::error::bad_descriptor); +    else      { -      this->get_io_service().post(bind_handler(handler, ec)); -      return; +      DWORD bytes_transferred = 0; +      DWORD recv_flags = flags; +      int result = ::WSARecvFrom(impl.socket_, buffers, +          buffer_count, &bytes_transferred, &recv_flags, +          sender_endpoint.data(), endpoint_size, op, 0); +      DWORD last_error = ::WSAGetLastError(); +      if (last_error == ERROR_PORT_UNREACHABLE) +        last_error = WSAECONNREFUSED; +      if (result != 0 && last_error != WSA_IO_PENDING) +        iocp_service_.on_completion(op, last_error, bytes_transferred); +      else +        iocp_service_.on_pending(op);      } +  } -    // Start the connect operation. -    if (socket_ops::connect(impl.socket_, peer_endpoint.data(), -          peer_endpoint.size(), ec) == 0) +  // Helper function to start an asynchronous receive_from operation. +  void start_accept_op(implementation_type& impl, +      bool peer_is_open, socket_holder& new_socket, +      void* output_buffer, DWORD address_length, operation* op) +  { +    update_cancellation_thread_id(impl); +    iocp_service_.work_started(); + +    if (!is_open(impl)) +      iocp_service_.on_completion(op, boost::asio::error::bad_descriptor); +    else if (peer_is_open) +      iocp_service_.on_completion(op, boost::asio::error::already_open); +    else      { -      // Revert socket to blocking mode unless the user requested otherwise. -      if (!(impl.flags_ & implementation_type::user_set_non_blocking)) +      boost::system::error_code ec; +      new_socket.reset(socket_ops::socket(impl.protocol_.family(), +            impl.protocol_.type(), impl.protocol_.protocol(), ec)); +      if (new_socket.get() == invalid_socket) +        iocp_service_.on_completion(op, ec); +      else        { -        non_blocking = 0; -        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec); +        DWORD bytes_read = 0; +        BOOL result = ::AcceptEx(impl.socket_, new_socket.get(), output_buffer, +            0, address_length, address_length, &bytes_read, op); +        DWORD last_error = ::WSAGetLastError(); +        if (!result && last_error != WSA_IO_PENDING) +          iocp_service_.on_completion(op, last_error); +        else +          iocp_service_.on_pending(op);        } - -      // The connect operation has finished successfully so we need to post the -      // handler immediately. -      this->get_io_service().post(bind_handler(handler, ec));      } -    else if (ec == boost::asio::error::in_progress -        || ec == boost::asio::error::would_block) +  } + +  // Start an asynchronous read or write operation using the the reactor. +  void start_reactor_op(implementation_type& impl, int op_type, reactor_op* op) +  { +    reactor& r = get_reactor(); +    update_cancellation_thread_id(impl); + +    if (is_open(impl))      { -      // The connection is happening in the background, and we need to wait -      // until the socket becomes writeable. -      boost::shared_ptr<bool> completed(new bool(false)); -      reactor->start_connect_op(impl.socket_, impl.reactor_data_, -          connect_operation<Handler>( -            impl.socket_, -            (impl.flags_ & implementation_type::user_set_non_blocking) != 0, -            this->get_io_service(), handler)); +      r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false); +      return;      }      else +      op->ec_ = boost::asio::error::bad_descriptor; + +    iocp_service_.post_immediate_completion(op); +  } + +  // Start the asynchronous connect operation using the reactor. +  void start_connect_op(implementation_type& impl, +      reactor_op* op, const endpoint_type& peer_endpoint) +  { +    reactor& r = get_reactor(); +    update_cancellation_thread_id(impl); + +    if (is_open(impl))      { -      // Revert socket to blocking mode unless the user requested otherwise. -      if (!(impl.flags_ & implementation_type::user_set_non_blocking)) +      ioctl_arg_type non_blocking = 1; +      if (!socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_))        { -        non_blocking = 0; -        boost::system::error_code ignored_ec; -        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); -      } +        if (socket_ops::connect(impl.socket_, peer_endpoint.data(), +              peer_endpoint.size(), op->ec_) != 0) +        { +          if (!op->ec_ +              && !(impl.flags_ & implementation_type::user_set_non_blocking)) +          { +            non_blocking = 0; +            socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_); +          } -      // The connect operation has failed, so post the handler immediately. -      this->get_io_service().post(bind_handler(handler, ec)); +          if (op->ec_ == boost::asio::error::in_progress +              || op->ec_ == boost::asio::error::would_block) +          { +            op->ec_ = boost::system::error_code(); +            r.start_op(reactor::connect_op, impl.socket_, +                impl.reactor_data_, op, true); +            return; +          } +        } +      }      } +    else +      op->ec_ = boost::asio::error::bad_descriptor; + +    iocp_service_.post_immediate_completion(op);    } -private:    // Helper function to close a socket when the associated object is being    // destroyed.    void close_for_destruction(implementation_type& impl) @@ -2317,11 +1896,11 @@ private:        // Check if the reactor was created, in which case we need to close the        // socket on the reactor as well to cancel any operations that might be        // running there. -      reactor_type* reactor = static_cast<reactor_type*>( +      reactor* r = static_cast<reactor*>(              interlocked_compare_exchange_pointer(                reinterpret_cast<void**>(&reactor_), 0, 0)); -      if (reactor) -        reactor->close_descriptor(impl.socket_, impl.reactor_data_); +      if (r) +        r->close_descriptor(impl.socket_, impl.reactor_data_);        // The socket destructor must not block. If the user has changed the        // linger option to block in the foreground, we will change it back to the @@ -2347,6 +1926,35 @@ private:      }    } +  // Update the ID of the thread from which cancellation is safe. +  void update_cancellation_thread_id(implementation_type& impl) +  { +#if defined(BOOST_ASIO_ENABLE_CANCELIO) +    if (impl.safe_cancellation_thread_id_ == 0) +      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); +    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) +      impl.safe_cancellation_thread_id_ = ~DWORD(0); +#else // defined(BOOST_ASIO_ENABLE_CANCELIO) +    (void)impl; +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) +  } + +  // Helper function to get the reactor. If no reactor has been created yet, a +  // new one is obtained from the io_service and a pointer to it is cached in +  // this service. +  reactor& get_reactor() +  { +    reactor* r = static_cast<reactor*>( +          interlocked_compare_exchange_pointer( +            reinterpret_cast<void**>(&reactor_), 0, 0)); +    if (!r) +    { +      r = &(use_service<reactor>(io_service_)); +      interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r); +    } +    return *r; +  } +    // Helper function to emulate InterlockedCompareExchangePointer functionality    // for:    // - very old Platform SDKs; and @@ -2375,13 +1983,16 @@ private:  #endif    } +  // The io_service used to obtain the reactor, if required. +  boost::asio::io_service& io_service_; +    // The IOCP service used for running asynchronous operations and dispatching    // handlers.    win_iocp_io_service& iocp_service_;    // The reactor used for performing connect operations. This object is created    // only if needed. -  reactor_type* reactor_; +  reactor* reactor_;    // Mutex to protect access to the linked list of implementations.     boost::asio::detail::mutex mutex_; diff --git a/3rdParty/Boost/src/boost/asio/detail/win_mutex.hpp b/3rdParty/Boost/src/boost/asio/detail/win_mutex.hpp index 107d707..176a5fd 100644 --- a/3rdParty/Boost/src/boost/asio/detail/win_mutex.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/win_mutex.hpp @@ -66,15 +66,7 @@ public:    // Lock the mutex.    void lock()    { -    int error = do_lock(); -    if (error != 0) -    { -      boost::system::system_error e( -          boost::system::error_code(error, -            boost::asio::error::get_system_category()), -          "mutex"); -      boost::throw_exception(e); -    } +    ::EnterCriticalSection(&crit_section_);    }    // Unlock the mutex. @@ -92,12 +84,20 @@ private:  #if defined(__MINGW32__)      // Not sure if MinGW supports structured exception handling, so for now      // we'll just call the Windows API and hope. +# if defined(UNDER_CE)      ::InitializeCriticalSection(&crit_section_); +# else +    ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000); +# endif      return 0;  #else      __try      { +# if defined(UNDER_CE)        ::InitializeCriticalSection(&crit_section_); +# else +      ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000); +# endif      }      __except(GetExceptionCode() == STATUS_NO_MEMORY          ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) @@ -109,34 +109,6 @@ private:  #endif    } -  // Locking must be performed in a separate function to lock() since the -  // compiler does not support the use of structured exceptions and C++ -  // exceptions in the same function. -  int do_lock() -  { -#if defined(__MINGW32__) -    // Not sure if MinGW supports structured exception handling, so for now -    // we'll just call the Windows API and hope. -    ::EnterCriticalSection(&crit_section_); -    return 0; -#else -    __try -    { -      ::EnterCriticalSection(&crit_section_); -    } -    __except(GetExceptionCode() == STATUS_INVALID_HANDLE -        || GetExceptionCode() == STATUS_NO_MEMORY -        ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) -    { -      if (GetExceptionCode() == STATUS_NO_MEMORY) -        return ERROR_OUTOFMEMORY; -      return ERROR_INVALID_HANDLE; -    } - -    return 0; -#endif -  } -    ::CRITICAL_SECTION crit_section_;  }; diff --git a/3rdParty/Boost/src/boost/asio/impl/io_service.ipp b/3rdParty/Boost/src/boost/asio/impl/io_service.ipp index 9234dc4..20f868d 100644 --- a/3rdParty/Boost/src/boost/asio/impl/io_service.ipp +++ b/3rdParty/Boost/src/boost/asio/impl/io_service.ipp @@ -26,18 +26,9 @@  #if defined(BOOST_ASIO_HAS_IOCP)  # include <boost/asio/detail/win_iocp_io_service.hpp> -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include <boost/asio/detail/epoll_reactor.hpp> -# include <boost/asio/detail/task_io_service.hpp> -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include <boost/asio/detail/kqueue_reactor.hpp> -# include <boost/asio/detail/task_io_service.hpp> -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include <boost/asio/detail/dev_poll_reactor.hpp> -# include <boost/asio/detail/task_io_service.hpp>  #else -# include <boost/asio/detail/select_reactor.hpp>  # include <boost/asio/detail/task_io_service.hpp> +# include <boost/asio/detail/reactor.hpp>  #endif  namespace boost { @@ -176,7 +167,6 @@ inline boost::asio::io_service& io_service::work::get_io_service()  inline io_service::service::service(boost::asio::io_service& owner)    : owner_(owner), -    type_info_(0),      next_(0)  {  } diff --git a/3rdParty/Boost/src/boost/asio/impl/read.ipp b/3rdParty/Boost/src/boost/asio/impl/read.ipp index 05ea960..772c06b 100644 --- a/3rdParty/Boost/src/boost/asio/impl/read.ipp +++ b/3rdParty/Boost/src/boost/asio/impl/read.ipp @@ -24,6 +24,7 @@  #include <boost/asio/buffer.hpp>  #include <boost/asio/completion_condition.hpp>  #include <boost/asio/error.hpp> +#include <boost/asio/detail/base_from_completion_cond.hpp>  #include <boost/asio/detail/bind_handler.hpp>  #include <boost/asio/detail/consuming_buffers.hpp>  #include <boost/asio/detail/handler_alloc_helpers.hpp> @@ -42,14 +43,14 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,    boost::asio::detail::consuming_buffers<      mutable_buffer, MutableBufferSequence> tmp(buffers);    std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( +  tmp.prepare(detail::adapt_completion_condition_result(          completion_condition(ec, total_transferred)));    while (tmp.begin() != tmp.end())    {      std::size_t bytes_transferred = s.read_some(tmp, ec);      tmp.consume(bytes_transferred);      total_transferred += bytes_transferred; -    tmp.set_max_size(detail::adapt_completion_condition_result( +    tmp.prepare(detail::adapt_completion_condition_result(            completion_condition(ec, total_transferred)));    }    return total_transferred; @@ -130,51 +131,111 @@ namespace detail  {    template <typename AsyncReadStream, typename MutableBufferSequence,        typename CompletionCondition, typename ReadHandler> -  class read_handler +  class read_op +    : detail::base_from_completion_cond<CompletionCondition>    {    public: -    typedef boost::asio::detail::consuming_buffers< -      mutable_buffer, MutableBufferSequence> buffers_type; - -    read_handler(AsyncReadStream& stream, const buffers_type& buffers, +    read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,          CompletionCondition completion_condition, ReadHandler handler) -      : stream_(stream), +      : detail::base_from_completion_cond< +          CompletionCondition>(completion_condition), +        stream_(stream),          buffers_(buffers),          total_transferred_(0), -        completion_condition_(completion_condition), -        handler_(handler) +        handler_(handler), +        start_(true)      {      }      void operator()(const boost::system::error_code& ec,          std::size_t bytes_transferred)      { -      total_transferred_ += bytes_transferred; -      buffers_.consume(bytes_transferred); -      buffers_.set_max_size(detail::adapt_completion_condition_result( -            completion_condition_(ec, total_transferred_))); -      if (buffers_.begin() == buffers_.end()) +      switch (start_)        { +        case true: start_ = false; +        buffers_.prepare(this->check(ec, total_transferred_)); +        for (;;) +        { +          stream_.async_read_some(buffers_, *this); +          return; default: +          total_transferred_ += bytes_transferred; +          buffers_.consume(bytes_transferred); +          buffers_.prepare(this->check(ec, total_transferred_)); +          if ((!ec && bytes_transferred == 0) +              || buffers_.begin() == buffers_.end()) +            break; +        } +          handler_(ec, total_transferred_);        } -      else +    } + +  //private: +    AsyncReadStream& stream_; +    boost::asio::detail::consuming_buffers< +      mutable_buffer, MutableBufferSequence> buffers_; +    std::size_t total_transferred_; +    ReadHandler handler_; +    bool start_; +  }; + +  template <typename AsyncReadStream, +      typename CompletionCondition, typename ReadHandler> +  class read_op<AsyncReadStream, boost::asio::mutable_buffers_1, +      CompletionCondition, ReadHandler> +    : detail::base_from_completion_cond<CompletionCondition> +  { +  public: +    read_op(AsyncReadStream& stream, +        const boost::asio::mutable_buffers_1& buffers, +        CompletionCondition completion_condition, +        ReadHandler handler) +      : detail::base_from_completion_cond< +          CompletionCondition>(completion_condition), +        stream_(stream), +        buffer_(buffers), +        total_transferred_(0), +        handler_(handler), +        start_(true) +    { +    } + +    void operator()(const boost::system::error_code& ec, +        std::size_t bytes_transferred) +    { +      std::size_t n = 0; +      switch (start_)        { -        stream_.async_read_some(buffers_, *this); +        case true: start_ = false; +        n = this->check(ec, total_transferred_); +        for (;;) +        { +          stream_.async_read_some(boost::asio::buffer( +                buffer_ + total_transferred_, n), *this); +          return; default: +          total_transferred_ += bytes_transferred; +          if ((!ec && bytes_transferred == 0) +              || (n = this->check(ec, total_transferred_)) == 0 +              || total_transferred_ == boost::asio::buffer_size(buffer_)) +            break; +        } + +        handler_(ec, total_transferred_);        }      }    //private:      AsyncReadStream& stream_; -    buffers_type buffers_; +    boost::asio::mutable_buffer buffer_;      std::size_t total_transferred_; -    CompletionCondition completion_condition_;      ReadHandler handler_; +    bool start_;    };    template <typename AsyncReadStream, typename MutableBufferSequence,        typename CompletionCondition, typename ReadHandler>    inline void* asio_handler_allocate(std::size_t size, -      read_handler<AsyncReadStream, MutableBufferSequence, +      read_op<AsyncReadStream, MutableBufferSequence,          CompletionCondition, ReadHandler>* this_handler)    {      return boost_asio_handler_alloc_helpers::allocate( @@ -184,7 +245,7 @@ namespace detail    template <typename AsyncReadStream, typename MutableBufferSequence,        typename CompletionCondition, typename ReadHandler>    inline void asio_handler_deallocate(void* pointer, std::size_t size, -      read_handler<AsyncReadStream, MutableBufferSequence, +      read_op<AsyncReadStream, MutableBufferSequence,          CompletionCondition, ReadHandler>* this_handler)    {      boost_asio_handler_alloc_helpers::deallocate( @@ -195,7 +256,7 @@ namespace detail        typename MutableBufferSequence, typename CompletionCondition,        typename ReadHandler>    inline void asio_handler_invoke(const Function& function, -      read_handler<AsyncReadStream, MutableBufferSequence, +      read_op<AsyncReadStream, MutableBufferSequence,          CompletionCondition, ReadHandler>* this_handler)    {      boost_asio_handler_invoke_helpers::invoke( @@ -208,24 +269,10 @@ template <typename AsyncReadStream, typename MutableBufferSequence,  inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,      CompletionCondition completion_condition, ReadHandler handler)  { -  boost::asio::detail::consuming_buffers< -    mutable_buffer, MutableBufferSequence> tmp(buffers); - -  boost::system::error_code ec; -  std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( -        completion_condition(ec, total_transferred))); -  if (tmp.begin() == tmp.end()) -  { -    s.get_io_service().post(detail::bind_handler( -          handler, ec, total_transferred)); -    return; -  } - -  s.async_read_some(tmp, -      detail::read_handler<AsyncReadStream, MutableBufferSequence, -        CompletionCondition, ReadHandler>( -          s, tmp, completion_condition, handler)); +  detail::read_op<AsyncReadStream, MutableBufferSequence, +    CompletionCondition, ReadHandler>( +      s, buffers, completion_condition, handler)( +        boost::system::error_code(), 0);  }  template <typename AsyncReadStream, typename MutableBufferSequence, @@ -242,52 +289,64 @@ namespace detail  {    template <typename AsyncReadStream, typename Allocator,        typename CompletionCondition, typename ReadHandler> -  class read_streambuf_handler +  class read_streambuf_op +    : detail::base_from_completion_cond<CompletionCondition>    {    public: -    read_streambuf_handler(AsyncReadStream& stream, +    read_streambuf_op(AsyncReadStream& stream,          basic_streambuf<Allocator>& streambuf,          CompletionCondition completion_condition, ReadHandler handler) -      : stream_(stream), +      : detail::base_from_completion_cond< +          CompletionCondition>(completion_condition), +        stream_(stream),          streambuf_(streambuf),          total_transferred_(0), -        completion_condition_(completion_condition), -        handler_(handler) +        handler_(handler), +        start_(true)      {      }      void operator()(const boost::system::error_code& ec,          std::size_t bytes_transferred)      { -      total_transferred_ += bytes_transferred; -      streambuf_.commit(bytes_transferred); -      std::size_t max_size = detail::adapt_completion_condition_result( -            completion_condition_(ec, total_transferred_)); -      std::size_t bytes_available = std::min<std::size_t>(512, -          std::min<std::size_t>(max_size, -            streambuf_.max_size() - streambuf_.size())); -      if (bytes_available == 0) +      std::size_t max_size, bytes_available; +      switch (start_)        { +        case true: start_ = false; +        max_size = this->check(ec, total_transferred_); +        bytes_available = std::min<std::size_t>(512, +            std::min<std::size_t>(max_size, +              streambuf_.max_size() - streambuf_.size())); +        for (;;) +        { +          stream_.async_read_some(streambuf_.prepare(bytes_available), *this); +          return; default: +          total_transferred_ += bytes_transferred; +          streambuf_.commit(bytes_transferred); +          max_size = this->check(ec, total_transferred_); +          bytes_available = std::min<std::size_t>(512, +              std::min<std::size_t>(max_size, +                streambuf_.max_size() - streambuf_.size())); +          if ((!ec && bytes_transferred == 0) || bytes_available == 0) +            break; +        } +          handler_(ec, total_transferred_);        } -      else -      { -        stream_.async_read_some(streambuf_.prepare(bytes_available), *this); -      }      }    //private:      AsyncReadStream& stream_;      boost::asio::basic_streambuf<Allocator>& streambuf_;      std::size_t total_transferred_; -    CompletionCondition completion_condition_;      ReadHandler handler_; +    bool start_;    };    template <typename AsyncReadStream, typename Allocator,        typename CompletionCondition, typename ReadHandler>    inline void* asio_handler_allocate(std::size_t size, -      read_streambuf_handler<AsyncReadStream, Allocator, +      read_streambuf_op<AsyncReadStream, Allocator,          CompletionCondition, ReadHandler>* this_handler)    {      return boost_asio_handler_alloc_helpers::allocate( @@ -297,7 +356,7 @@ namespace detail    template <typename AsyncReadStream, typename Allocator,        typename CompletionCondition, typename ReadHandler>    inline void asio_handler_deallocate(void* pointer, std::size_t size, -      read_streambuf_handler<AsyncReadStream, Allocator, +      read_streambuf_op<AsyncReadStream, Allocator,          CompletionCondition, ReadHandler>* this_handler)    {      boost_asio_handler_alloc_helpers::deallocate( @@ -307,7 +366,7 @@ namespace detail    template <typename Function, typename AsyncReadStream,        typename Allocator, typename CompletionCondition, typename ReadHandler>    inline void asio_handler_invoke(const Function& function, -      read_streambuf_handler<AsyncReadStream, Allocator, +      read_streambuf_op<AsyncReadStream, Allocator,          CompletionCondition, ReadHandler>* this_handler)    {      boost_asio_handler_invoke_helpers::invoke( @@ -321,23 +380,10 @@ inline void async_read(AsyncReadStream& s,      boost::asio::basic_streambuf<Allocator>& b,      CompletionCondition completion_condition, ReadHandler handler)  { -  boost::system::error_code ec; -  std::size_t total_transferred = 0; -  std::size_t max_size = detail::adapt_completion_condition_result( -        completion_condition(ec, total_transferred)); -  std::size_t bytes_available = std::min<std::size_t>(512, -      std::min<std::size_t>(max_size, b.max_size() - b.size())); -  if (bytes_available == 0) -  { -    s.get_io_service().post(detail::bind_handler( -          handler, ec, total_transferred)); -    return; -  } - -  s.async_read_some(b.prepare(bytes_available), -      detail::read_streambuf_handler<AsyncReadStream, Allocator, -        CompletionCondition, ReadHandler>( -          s, b, completion_condition, handler)); +  detail::read_streambuf_op<AsyncReadStream, +    Allocator, CompletionCondition, ReadHandler>( +      s, b, completion_condition, handler)( +        boost::system::error_code(), 0);  }  template <typename AsyncReadStream, typename Allocator, typename ReadHandler> diff --git a/3rdParty/Boost/src/boost/asio/impl/read_at.ipp b/3rdParty/Boost/src/boost/asio/impl/read_at.ipp index 91fd014..eb3c3f8 100644 --- a/3rdParty/Boost/src/boost/asio/impl/read_at.ipp +++ b/3rdParty/Boost/src/boost/asio/impl/read_at.ipp @@ -43,7 +43,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,    boost::asio::detail::consuming_buffers<      mutable_buffer, MutableBufferSequence> tmp(buffers);    std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( +  tmp.prepare(detail::adapt_completion_condition_result(          completion_condition(ec, total_transferred)));    while (tmp.begin() != tmp.end())    { @@ -51,7 +51,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,          offset + total_transferred, tmp, ec);      tmp.consume(bytes_transferred);      total_transferred += bytes_transferred; -    tmp.set_max_size(detail::adapt_completion_condition_result( +    tmp.prepare(detail::adapt_completion_condition_result(            completion_condition(ec, total_transferred)));    }    return total_transferred; @@ -158,7 +158,7 @@ namespace detail      {        total_transferred_ += bytes_transferred;        buffers_.consume(bytes_transferred); -      buffers_.set_max_size(detail::adapt_completion_condition_result( +      buffers_.prepare(detail::adapt_completion_condition_result(              completion_condition_(ec, total_transferred_)));        if (buffers_.begin() == buffers_.end())        { @@ -225,7 +225,7 @@ inline void async_read_at(AsyncRandomAccessReadDevice& d,    boost::system::error_code ec;    std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( +  tmp.prepare(detail::adapt_completion_condition_result(          completion_condition(ec, total_transferred)));    if (tmp.begin() == tmp.end())    { diff --git a/3rdParty/Boost/src/boost/asio/impl/write.ipp b/3rdParty/Boost/src/boost/asio/impl/write.ipp index 76bace3..28a5273 100644 --- a/3rdParty/Boost/src/boost/asio/impl/write.ipp +++ b/3rdParty/Boost/src/boost/asio/impl/write.ipp @@ -19,6 +19,7 @@  #include <boost/asio/buffer.hpp>  #include <boost/asio/completion_condition.hpp> +#include <boost/asio/detail/base_from_completion_cond.hpp>  #include <boost/asio/detail/bind_handler.hpp>  #include <boost/asio/detail/consuming_buffers.hpp>  #include <boost/asio/detail/handler_alloc_helpers.hpp> @@ -37,14 +38,14 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,    boost::asio::detail::consuming_buffers<      const_buffer, ConstBufferSequence> tmp(buffers);    std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( +  tmp.prepare(detail::adapt_completion_condition_result(          completion_condition(ec, total_transferred)));    while (tmp.begin() != tmp.end())    {      std::size_t bytes_transferred = s.write_some(tmp, ec);      tmp.consume(bytes_transferred);      total_transferred += bytes_transferred; -    tmp.set_max_size(detail::adapt_completion_condition_result( +    tmp.prepare(detail::adapt_completion_condition_result(            completion_condition(ec, total_transferred)));    }    return total_transferred; @@ -111,51 +112,164 @@ namespace detail  {    template <typename AsyncWriteStream, typename ConstBufferSequence,        typename CompletionCondition, typename WriteHandler> -  class write_handler +  class write_op +    : detail::base_from_completion_cond<CompletionCondition>    {    public: -    typedef boost::asio::detail::consuming_buffers< -      const_buffer, ConstBufferSequence> buffers_type; - -    write_handler(AsyncWriteStream& stream, const buffers_type& buffers, +    write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,          CompletionCondition completion_condition, WriteHandler handler) -      : stream_(stream), +      : detail::base_from_completion_cond< +          CompletionCondition>(completion_condition), +        stream_(stream),          buffers_(buffers),          total_transferred_(0), -        completion_condition_(completion_condition), -        handler_(handler) +        handler_(handler), +        start_(true) +    { +    } + +    void operator()(const boost::system::error_code& ec, +        std::size_t bytes_transferred) +    { +      switch (start_) +      { +        case true: start_ = false; +        buffers_.prepare(this->check(ec, total_transferred_)); +        for (;;) +        { +          stream_.async_write_some(buffers_, *this); +          return; default: +          total_transferred_ += bytes_transferred; +          buffers_.consume(bytes_transferred); +          buffers_.prepare(this->check(ec, total_transferred_)); +          if ((!ec && bytes_transferred == 0) +              || buffers_.begin() == buffers_.end()) +            break; +        } + +        handler_(ec, total_transferred_); +      } +    } + +  //private: +    AsyncWriteStream& stream_; +    boost::asio::detail::consuming_buffers< +      const_buffer, ConstBufferSequence> buffers_; +    std::size_t total_transferred_; +    WriteHandler handler_; +    bool start_; +  }; + +  template <typename AsyncWriteStream, +      typename CompletionCondition, typename WriteHandler> +  class write_op<AsyncWriteStream, boost::asio::mutable_buffers_1, +      CompletionCondition, WriteHandler> +    : detail::base_from_completion_cond<CompletionCondition> +  { +  public: +    write_op(AsyncWriteStream& stream, +        const boost::asio::mutable_buffers_1& buffers, +        CompletionCondition completion_condition, +        WriteHandler handler) +      : detail::base_from_completion_cond< +          CompletionCondition>(completion_condition), +        stream_(stream), +        buffer_(buffers), +        total_transferred_(0), +        handler_(handler), +        start_(true)      {      }      void operator()(const boost::system::error_code& ec,          std::size_t bytes_transferred)      { -      total_transferred_ += bytes_transferred; -      buffers_.consume(bytes_transferred); -      buffers_.set_max_size(detail::adapt_completion_condition_result( -            completion_condition_(ec, total_transferred_))); -      if (buffers_.begin() == buffers_.end()) +      std::size_t n = 0; +      switch (start_)        { +        case true: start_ = false; +        n = this->check(ec, total_transferred_); +        for (;;) +        { +          stream_.async_write_some(boost::asio::buffer( +                buffer_ + total_transferred_, n), *this); +          return; default: +          total_transferred_ += bytes_transferred; +          if ((!ec && bytes_transferred == 0) +              || (n = this->check(ec, total_transferred_)) == 0 +              || total_transferred_ == boost::asio::buffer_size(buffer_)) +            break; +        } +          handler_(ec, total_transferred_);        } -      else +    } + +  //private: +    AsyncWriteStream& stream_; +    boost::asio::mutable_buffer buffer_; +    std::size_t total_transferred_; +    WriteHandler handler_; +    bool start_; +  }; + +  template <typename AsyncWriteStream, +      typename CompletionCondition, typename WriteHandler> +  class write_op<AsyncWriteStream, boost::asio::const_buffers_1, +      CompletionCondition, WriteHandler> +    : detail::base_from_completion_cond<CompletionCondition> +  { +  public: +    write_op(AsyncWriteStream& stream, +        const boost::asio::const_buffers_1& buffers, +        CompletionCondition completion_condition, +        WriteHandler handler) +      : detail::base_from_completion_cond< +          CompletionCondition>(completion_condition), +        stream_(stream), +        buffer_(buffers), +        total_transferred_(0), +        handler_(handler), +        start_(true) +    { +    } + +    void operator()(const boost::system::error_code& ec, +        std::size_t bytes_transferred) +    { +      std::size_t n = 0; +      switch (start_)        { -        stream_.async_write_some(buffers_, *this); +        case true: start_ = false; +        n = this->check(ec, total_transferred_); +        for (;;) +        { +          stream_.async_write_some(boost::asio::buffer( +                buffer_ + total_transferred_, n), *this); +          return; default: +          total_transferred_ += bytes_transferred; +          if ((!ec && bytes_transferred == 0) +              || (n = this->check(ec, total_transferred_)) == 0 +              || total_transferred_ == boost::asio::buffer_size(buffer_)) +            break; +        } + +        handler_(ec, total_transferred_);        }      }    //private:      AsyncWriteStream& stream_; -    buffers_type buffers_; +    boost::asio::const_buffer buffer_;      std::size_t total_transferred_; -    CompletionCondition completion_condition_;      WriteHandler handler_; +    bool start_;    };    template <typename AsyncWriteStream, typename ConstBufferSequence,        typename CompletionCondition, typename WriteHandler>    inline void* asio_handler_allocate(std::size_t size, -      write_handler<AsyncWriteStream, ConstBufferSequence, +      write_op<AsyncWriteStream, ConstBufferSequence,          CompletionCondition, WriteHandler>* this_handler)    {      return boost_asio_handler_alloc_helpers::allocate( @@ -165,7 +279,7 @@ namespace detail    template <typename AsyncWriteStream, typename ConstBufferSequence,        typename CompletionCondition, typename WriteHandler>    inline void asio_handler_deallocate(void* pointer, std::size_t size, -      write_handler<AsyncWriteStream, ConstBufferSequence, +      write_op<AsyncWriteStream, ConstBufferSequence,          CompletionCondition, WriteHandler>* this_handler)    {      boost_asio_handler_alloc_helpers::deallocate( @@ -176,7 +290,7 @@ namespace detail        typename ConstBufferSequence, typename CompletionCondition,        typename WriteHandler>    inline void asio_handler_invoke(const Function& function, -      write_handler<AsyncWriteStream, ConstBufferSequence, +      write_op<AsyncWriteStream, ConstBufferSequence,          CompletionCondition, WriteHandler>* this_handler)    {      boost_asio_handler_invoke_helpers::invoke( @@ -189,24 +303,10 @@ template <typename AsyncWriteStream, typename ConstBufferSequence,  inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,      CompletionCondition completion_condition, WriteHandler handler)  { -  boost::asio::detail::consuming_buffers< -    const_buffer, ConstBufferSequence> tmp(buffers); - -  boost::system::error_code ec; -  std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( -        completion_condition(ec, total_transferred))); -  if (tmp.begin() == tmp.end()) -  { -    s.get_io_service().post(detail::bind_handler( -          handler, ec, total_transferred)); -    return; -  } - -  s.async_write_some(tmp, -      detail::write_handler<AsyncWriteStream, ConstBufferSequence, -        CompletionCondition, WriteHandler>( -          s, tmp, completion_condition, handler)); +  detail::write_op<AsyncWriteStream, ConstBufferSequence, +    CompletionCondition, WriteHandler>( +      s, buffers, completion_condition, handler)( +        boost::system::error_code(), 0);  }  template <typename AsyncWriteStream, typename ConstBufferSequence, diff --git a/3rdParty/Boost/src/boost/asio/impl/write_at.ipp b/3rdParty/Boost/src/boost/asio/impl/write_at.ipp index 751229b..3d1a112 100644 --- a/3rdParty/Boost/src/boost/asio/impl/write_at.ipp +++ b/3rdParty/Boost/src/boost/asio/impl/write_at.ipp @@ -38,7 +38,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,    boost::asio::detail::consuming_buffers<      const_buffer, ConstBufferSequence> tmp(buffers);    std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( +  tmp.prepare(detail::adapt_completion_condition_result(          completion_condition(ec, total_transferred)));    while (tmp.begin() != tmp.end())    { @@ -46,7 +46,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,          offset + total_transferred, tmp, ec);      tmp.consume(bytes_transferred);      total_transferred += bytes_transferred; -    tmp.set_max_size(detail::adapt_completion_condition_result( +    tmp.prepare(detail::adapt_completion_condition_result(            completion_condition(ec, total_transferred)));    }    return total_transferred; @@ -142,7 +142,7 @@ namespace detail      {        total_transferred_ += bytes_transferred;        buffers_.consume(bytes_transferred); -      buffers_.set_max_size(detail::adapt_completion_condition_result( +      buffers_.prepare(detail::adapt_completion_condition_result(              completion_condition_(ec, total_transferred_)));        if (buffers_.begin() == buffers_.end())        { @@ -207,7 +207,7 @@ inline void async_write_at(AsyncRandomAccessWriteDevice& d,    boost::system::error_code ec;    std::size_t total_transferred = 0; -  tmp.set_max_size(detail::adapt_completion_condition_result( +  tmp.prepare(detail::adapt_completion_condition_result(          completion_condition(ec, total_transferred)));    if (tmp.begin() == tmp.end())    { diff --git a/3rdParty/Boost/src/boost/asio/io_service.hpp b/3rdParty/Boost/src/boost/asio/io_service.hpp index a34d874..3863e96 100644 --- a/3rdParty/Boost/src/boost/asio/io_service.hpp +++ b/3rdParty/Boost/src/boost/asio/io_service.hpp @@ -26,11 +26,8 @@  #include <boost/system/error_code.hpp>  #include <boost/asio/detail/pop_options.hpp> -#include <boost/asio/detail/dev_poll_reactor_fwd.hpp> -#include <boost/asio/detail/epoll_reactor_fwd.hpp> -#include <boost/asio/detail/kqueue_reactor_fwd.hpp>  #include <boost/asio/detail/noncopyable.hpp> -#include <boost/asio/detail/select_reactor_fwd.hpp> +#include <boost/asio/detail/reactor_fwd.hpp>  #include <boost/asio/detail/service_registry_fwd.hpp>  #include <boost/asio/detail/signal_init.hpp>  #include <boost/asio/detail/task_io_service_fwd.hpp> @@ -46,6 +43,12 @@ 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); +#if defined(BOOST_ASIO_HAS_IOCP) +namespace detail { typedef win_iocp_io_service io_service_impl; } +#else +namespace detail { typedef task_io_service<reactor> io_service_impl; } +#endif +  /// Provides core I/O functionality.  /**   * The io_service class provides the core I/O functionality for users of the @@ -178,18 +181,9 @@ class io_service    : private noncopyable  {  private: -  // The type of the platform-specific implementation. +  typedef detail::io_service_impl impl_type;  #if defined(BOOST_ASIO_HAS_IOCP) -  typedef detail::win_iocp_io_service impl_type;    friend class detail::win_iocp_overlapped_ptr; -#elif defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::task_io_service<detail::epoll_reactor<false> > impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::task_io_service<detail::kqueue_reactor<false> > impl_type; -#elif defined(BOOST_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  public: @@ -406,6 +400,14 @@ public:     * @param handler The handler to be called. The io_service will make     * a copy of the handler object as required. The function signature of the     * handler must be: @code void handler(); @endcode +   * +   * @note This function throws an exception only if: +   * +   * @li the handler's @c asio_handler_allocate function; or +   * +   * @li the handler's copy constructor +   * +   * throws an exception.     */    template <typename CompletionHandler>    void dispatch(CompletionHandler handler); @@ -423,6 +425,14 @@ public:     * @param handler The handler to be called. The io_service will make     * a copy of the handler object as required. The function signature of the     * handler must be: @code void handler(); @endcode +   * +   * @note This function throws an exception only if: +   * +   * @li the handler's @c asio_handler_allocate function; or +   * +   * @li the handler's copy constructor +   * +   * throws an exception.     */    template <typename CompletionHandler>    void post(CompletionHandler handler); @@ -606,9 +616,14 @@ private:    virtual void shutdown_service() = 0;    friend class boost::asio::detail::service_registry; +  struct key +  { +    key() : type_info_(0), id_(0) {} +    const std::type_info* type_info_; +    const boost::asio::io_service::id* id_; +  } key_; +    boost::asio::io_service& owner_; -  const std::type_info* type_info_; -  const boost::asio::io_service::id* id_;    service* next_;  }; diff --git a/3rdParty/Boost/src/boost/asio/ip/address_v4.hpp b/3rdParty/Boost/src/boost/asio/ip/address_v4.hpp index e0088dc..47d36b5 100644 --- a/3rdParty/Boost/src/boost/asio/ip/address_v4.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/address_v4.hpp @@ -102,7 +102,7 @@ public:      return *this;    } -  /// Get the address in bytes. +  /// Get the address in bytes, in network byte order.    bytes_type to_bytes() const    {      using namespace std; // For memcpy. diff --git a/3rdParty/Boost/src/boost/asio/ip/address_v6.hpp b/3rdParty/Boost/src/boost/asio/ip/address_v6.hpp index 4105c8d..5685f08 100644 --- a/3rdParty/Boost/src/boost/asio/ip/address_v6.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/address_v6.hpp @@ -115,7 +115,7 @@ public:      scope_id_ = id;    } -  /// Get the address in bytes. +  /// Get the address in bytes, in network byte order.    bytes_type to_bytes() const    {      using namespace std; // For memcpy. diff --git a/3rdParty/Boost/src/boost/asio/ip/basic_resolver.hpp b/3rdParty/Boost/src/boost/asio/ip/basic_resolver.hpp index c4f13ab..0660ce5 100644 --- a/3rdParty/Boost/src/boost/asio/ip/basic_resolver.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/basic_resolver.hpp @@ -19,6 +19,8 @@  #include <boost/asio/basic_io_object.hpp>  #include <boost/asio/error.hpp> +#include <boost/asio/ip/basic_resolver_iterator.hpp> +#include <boost/asio/ip/basic_resolver_query.hpp>  #include <boost/asio/ip/resolver_service.hpp>  #include <boost/asio/detail/throw_error.hpp> @@ -48,10 +50,10 @@ public:    typedef typename InternetProtocol::endpoint endpoint_type;    /// The query type. -  typedef typename InternetProtocol::resolver_query query; +  typedef basic_resolver_query<InternetProtocol> query;    /// The iterator type. -  typedef typename InternetProtocol::resolver_iterator iterator; +  typedef basic_resolver_iterator<InternetProtocol> iterator;    /// Constructor.    /** diff --git a/3rdParty/Boost/src/boost/asio/ip/basic_resolver_iterator.hpp b/3rdParty/Boost/src/boost/asio/ip/basic_resolver_iterator.hpp index 90644a2..5f4937b 100644 --- a/3rdParty/Boost/src/boost/asio/ip/basic_resolver_iterator.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/basic_resolver_iterator.hpp @@ -18,8 +18,7 @@  #include <boost/asio/detail/push_options.hpp>  #include <boost/asio/detail/push_options.hpp> -#include <boost/iterator/iterator_facade.hpp> -#include <boost/optional.hpp> +#include <boost/iterator.hpp>  #include <boost/shared_ptr.hpp>  #include <cstring>  #include <string> @@ -48,14 +47,18 @@ namespace ip {   */  template <typename InternetProtocol>  class basic_resolver_iterator -  : public boost::iterator_facade< -        basic_resolver_iterator<InternetProtocol>, -        const basic_resolver_entry<InternetProtocol>, -        boost::forward_traversal_tag> +#if defined(GENERATING_DOCUMENTATION) +  : public std::iterator< +#else // defined(GENERATING_DOCUMENTATION) +  : public boost::iterator< +#endif // defined(GENERATING_DOCUMENTATION) +      std::forward_iterator_tag, +      const basic_resolver_entry<InternetProtocol> >  {  public:    /// Default constructor creates an end iterator.    basic_resolver_iterator() +    : index_(0)    {    } @@ -91,11 +94,6 @@ public:        address_info = address_info->ai_next;      } -    if (iter.values_->size()) -      iter.iter_ = iter.values_->begin(); -    else -      iter.values_.reset(); -      return iter;    } @@ -109,21 +107,58 @@ public:      iter.values_->push_back(          basic_resolver_entry<InternetProtocol>(            endpoint, host_name, service_name)); -    iter.iter_ = iter.values_->begin();      return iter;    } -private: -  friend class boost::iterator_core_access; +  /// Dereference an iterator. +  const basic_resolver_entry<InternetProtocol>& operator*() const +  { +    return dereference(); +  } + +  /// Dereference an iterator. +  const basic_resolver_entry<InternetProtocol>* operator->() const +  { +    return &dereference(); +  } + +  /// Increment operator (prefix). +  basic_resolver_iterator& operator++() +  { +    increment(); +    return *this; +  } +  /// Increment operator (postfix). +  basic_resolver_iterator operator++(int) +  { +    basic_resolver_iterator tmp(*this); +    ++*this; +    return tmp; +  } + +  /// Test two iterators for equality. +  friend bool operator==(const basic_resolver_iterator& a, +      const basic_resolver_iterator& b) +  { +    return a.equal(b); +  } + +  /// Test two iterators for inequality. +  friend bool operator!=(const basic_resolver_iterator& a, +      const basic_resolver_iterator& b) +  { +    return !a.equal(b); +  } + +private:    void increment()    { -    if (++*iter_ == values_->end()) +    if (++index_ == values_->size())      {        // Reset state to match a default constructed end iterator.        values_.reset(); -      typedef typename values_type::const_iterator values_iterator_type; -      iter_.reset(); +      index_ = 0;      }    } @@ -133,18 +168,17 @@ private:        return true;      if (values_ != other.values_)        return false; -    return *iter_ == *other.iter_; +    return index_ == other.index_;    }    const basic_resolver_entry<InternetProtocol>& dereference() const    { -    return **iter_; +    return (*values_)[index_];    }    typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; -  typedef typename values_type::const_iterator values_iter_type;    boost::shared_ptr<values_type> values_; -  boost::optional<values_iter_type> iter_; +  std::size_t index_;  };  } // namespace ip diff --git a/3rdParty/Boost/src/boost/asio/ip/basic_resolver_query.hpp b/3rdParty/Boost/src/boost/asio/ip/basic_resolver_query.hpp index e95362b..75d3c47 100644 --- a/3rdParty/Boost/src/boost/asio/ip/basic_resolver_query.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/basic_resolver_query.hpp @@ -47,14 +47,30 @@ public:    typedef InternetProtocol protocol_type;    /// Construct with specified service name for any protocol. +  /** +   * This constructor is typically used to perform name resolution for local +   * service binding. +   * +   * @param service_name A string identifying the requested service. This may +   * be a descriptive name or a numeric string corresponding to a port number. +   * +   * @param resolve_flags A set of flags that determine how name resolution +   * should be performed. The default flags are suitable for local service +   * binding. +   * +   * @note On POSIX systems, service names are typically defined in the file +   * <tt>/etc/services</tt>. On Windows, service names may be found in the file +   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems +   * may use additional locations when resolving service names. +   */    basic_resolver_query(const std::string& service_name, -      int flags = passive | address_configured) +      resolver_query_base::flags resolve_flags = passive | address_configured)      : hints_(),        host_name_(),        service_name_(service_name)    {      typename InternetProtocol::endpoint endpoint; -    hints_.ai_flags = flags; +    hints_.ai_flags = static_cast<int>(resolve_flags);      hints_.ai_family = PF_UNSPEC;      hints_.ai_socktype = endpoint.protocol().type();      hints_.ai_protocol = endpoint.protocol().protocol(); @@ -65,14 +81,33 @@ public:    }    /// Construct with specified service name for a given protocol. +  /** +   * This constructor is typically used to perform name resolution for local +   * service binding with a specific protocol version. +   * +   * @param protocol A protocol object, normally representing either the IPv4 or +   * IPv6 version of an internet protocol. +   * +   * @param service_name A string identifying the requested service. This may +   * be a descriptive name or a numeric string corresponding to a port number. +   * +   * @param resolve_flags A set of flags that determine how name resolution +   * should be performed. The default flags are suitable for local service +   * binding. +   * +   * @note On POSIX systems, service names are typically defined in the file +   * <tt>/etc/services</tt>. On Windows, service names may be found in the file +   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems +   * may use additional locations when resolving service names. +   */    basic_resolver_query(const protocol_type& protocol,        const std::string& service_name, -      int flags = passive | address_configured) +      resolver_query_base::flags resolve_flags = passive | address_configured)      : hints_(),        host_name_(),        service_name_(service_name)    { -    hints_.ai_flags = flags; +    hints_.ai_flags = static_cast<int>(resolve_flags);      hints_.ai_family = protocol.family();      hints_.ai_socktype = protocol.type();      hints_.ai_protocol = protocol.protocol(); @@ -83,14 +118,45 @@ public:    }    /// Construct with specified host name and service name for any protocol. +  /** +   * This constructor is typically used to perform name resolution for +   * communication with remote hosts. +   * +   * @param host_name A string identifying a location. May be a descriptive name +   * or a numeric address string. If an empty string and the passive flag has +   * been specified, the resolved endpoints are suitable for local service +   * binding. If an empty string and passive is not specified, the resolved +   * endpoints will use the loopback address. +   * +   * @param service_name A string identifying the requested service. This may +   * be a descriptive name or a numeric string corresponding to a port number. +   * May be an empty string, in which case all resolved endpoints will have a +   * port number of 0. +   * +   * @param resolve_flags A set of flags that determine how name resolution +   * should be performed. The default flags are suitable for communication with +   * remote hosts. +   * +   * @note On POSIX systems, host names may be locally defined in the file +   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file +   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name +   * resolution is performed using DNS. Operating systems may use additional +   * locations when resolving host names (such as NETBIOS names on Windows). +   * +   * On POSIX systems, service names are typically defined in the file +   * <tt>/etc/services</tt>. On Windows, service names may be found in the file +   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems +   * may use additional locations when resolving service names. +   */    basic_resolver_query(const std::string& host_name, -      const std::string& service_name, int flags = address_configured) +      const std::string& service_name, +      resolver_query_base::flags resolve_flags = address_configured)      : hints_(),        host_name_(host_name),        service_name_(service_name)    {      typename InternetProtocol::endpoint endpoint; -    hints_.ai_flags = flags; +    hints_.ai_flags = static_cast<int>(resolve_flags);      hints_.ai_family = PF_UNSPEC;      hints_.ai_socktype = endpoint.protocol().type();      hints_.ai_protocol = endpoint.protocol().protocol(); @@ -101,14 +167,47 @@ public:    }    /// Construct with specified host name and service name for a given protocol. +  /** +   * This constructor is typically used to perform name resolution for +   * communication with remote hosts. +   * +   * @param protocol A protocol object, normally representing either the IPv4 or +   * IPv6 version of an internet protocol. +   * +   * @param host_name A string identifying a location. May be a descriptive name +   * or a numeric address string. If an empty string and the passive flag has +   * been specified, the resolved endpoints are suitable for local service +   * binding. If an empty string and passive is not specified, the resolved +   * endpoints will use the loopback address. +   * +   * @param service_name A string identifying the requested service. This may +   * be a descriptive name or a numeric string corresponding to a port number. +   * May be an empty string, in which case all resolved endpoints will have a +   * port number of 0. +   * +   * @param resolve_flags A set of flags that determine how name resolution +   * should be performed. The default flags are suitable for communication with +   * remote hosts. +   * +   * @note On POSIX systems, host names may be locally defined in the file +   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file +   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name +   * resolution is performed using DNS. Operating systems may use additional +   * locations when resolving host names (such as NETBIOS names on Windows). +   * +   * On POSIX systems, service names are typically defined in the file +   * <tt>/etc/services</tt>. On Windows, service names may be found in the file +   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems +   * may use additional locations when resolving service names. +   */    basic_resolver_query(const protocol_type& protocol,        const std::string& host_name, const std::string& service_name, -      int flags = address_configured) +      resolver_query_base::flags resolve_flags = address_configured)      : hints_(),        host_name_(host_name),        service_name_(service_name)    { -    hints_.ai_flags = flags; +    hints_.ai_flags = static_cast<int>(resolve_flags);      hints_.ai_family = protocol.family();      hints_.ai_socktype = protocol.type();      hints_.ai_protocol = protocol.protocol(); diff --git a/3rdParty/Boost/src/boost/asio/ip/icmp.hpp b/3rdParty/Boost/src/boost/asio/ip/icmp.hpp index b70d87d..5d2fcab 100644 --- a/3rdParty/Boost/src/boost/asio/ip/icmp.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/icmp.hpp @@ -45,10 +45,10 @@ public:    /// The type of a ICMP endpoint.    typedef basic_endpoint<icmp> endpoint; -  /// The type of a resolver query. +  /// (Deprecated: use resolver::query.) The type of a resolver query.    typedef basic_resolver_query<icmp> resolver_query; -  /// The type of a resolver iterator. +  /// (Deprecated: use resolver::iterator.) The type of a resolver iterator.    typedef basic_resolver_iterator<icmp> resolver_iterator;    /// Construct to represent the IPv4 ICMP protocol. diff --git a/3rdParty/Boost/src/boost/asio/ip/resolver_query_base.hpp b/3rdParty/Boost/src/boost/asio/ip/resolver_query_base.hpp index d21b462..7fe1650 100644 --- a/3rdParty/Boost/src/boost/asio/ip/resolver_query_base.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/resolver_query_base.hpp @@ -35,58 +35,107 @@ class resolver_query_base  {  public:  #if defined(GENERATING_DOCUMENTATION) +  /// A bitmask type (C++ Std [lib.bitmask.types]). +  typedef unspecified flags; +    /// Determine the canonical name of the host specified in the query. -  static const int canonical_name = implementation_defined; +  static const flags canonical_name = implementation_defined;    /// Indicate that returned endpoint is intended for use as a locally bound    /// socket endpoint. -  static const int passive = implementation_defined; +  static const flags passive = implementation_defined;    /// Host name should be treated as a numeric string defining an IPv4 or IPv6    /// address and no name resolution should be attempted. -  static const int numeric_host = implementation_defined; +  static const flags numeric_host = implementation_defined;    /// Service name should be treated as a numeric string defining a port number    /// and no name resolution should be attempted. -  static const int numeric_service = implementation_defined; +  static const flags numeric_service = implementation_defined;    /// If the query protocol family is specified as IPv6, return IPv4-mapped    /// IPv6 addresses on finding no IPv6 addresses. -  static const int v4_mapped = implementation_defined; +  static const flags v4_mapped = implementation_defined;    /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses. -  static const int all_matching = implementation_defined; +  static const flags all_matching = implementation_defined;    /// Only return IPv4 addresses if a non-loopback IPv4 address is configured    /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address    /// is configured for the system. -  static const int address_configured = implementation_defined; +  static const flags address_configured = implementation_defined;  #else -  BOOST_STATIC_CONSTANT(int, canonical_name = AI_CANONNAME); -  BOOST_STATIC_CONSTANT(int, passive = AI_PASSIVE); -  BOOST_STATIC_CONSTANT(int, numeric_host = AI_NUMERICHOST); +  enum flags +  { +    canonical_name = AI_CANONNAME, +    passive = AI_PASSIVE, +    numeric_host = AI_NUMERICHOST,  # if defined(AI_NUMERICSERV) -  BOOST_STATIC_CONSTANT(int, numeric_service = AI_NUMERICSERV); +    numeric_service = AI_NUMERICSERV,  # else -  BOOST_STATIC_CONSTANT(int, numeric_service = 0); +    numeric_service = 0,  # endif -  // Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but -  // does not implement them. Therefore they are specifically excluded here. +    // Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but +    // does not implement them. Therefore they are specifically excluded here.  # if defined(AI_V4MAPPED) && !defined(__QNXNTO__) -  BOOST_STATIC_CONSTANT(int, v4_mapped = AI_V4MAPPED); +    v4_mapped = AI_V4MAPPED,  # else -  BOOST_STATIC_CONSTANT(int, v4_mapped = 0); +    v4_mapped = 0,  # endif  # if defined(AI_ALL) && !defined(__QNXNTO__) -  BOOST_STATIC_CONSTANT(int, all_matching = AI_ALL); +    all_matching = AI_ALL,  # else -  BOOST_STATIC_CONSTANT(int, all_matching = 0); +    all_matching = 0,  # endif  # if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__) -  BOOST_STATIC_CONSTANT(int, address_configured = AI_ADDRCONFIG); +    address_configured = AI_ADDRCONFIG  # else -  BOOST_STATIC_CONSTANT(int, address_configured = 0); +    address_configured = 0  # endif +  }; + +  // Implement bitmask operations as shown in C++ Std [lib.bitmask.types]. + +  friend flags operator&(flags x, flags y) +  { +    return static_cast<flags>( +        static_cast<unsigned int>(x) & static_cast<unsigned int>(y)); +  } + +  friend flags operator|(flags x, flags y) +  { +    return static_cast<flags>( +        static_cast<unsigned int>(x) | static_cast<unsigned int>(y)); +  } + +  friend flags operator^(flags x, flags y) +  { +    return static_cast<flags>( +        static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y)); +  } + +  friend flags operator~(flags x) +  { +    return static_cast<flags>(static_cast<unsigned int>(~x)); +  } + +  friend flags& operator&=(flags& x, flags y) +  { +    x = x & y; +    return x; +  } + +  friend flags& operator|=(flags& x, flags y) +  { +    x = x | y; +    return x; +  } + +  friend flags& operator^=(flags& x, flags y) +  { +    x = x ^ y; +    return x; +  }  #endif  protected: diff --git a/3rdParty/Boost/src/boost/asio/ip/resolver_service.hpp b/3rdParty/Boost/src/boost/asio/ip/resolver_service.hpp index 1cd12b9..ba59f6d 100644 --- a/3rdParty/Boost/src/boost/asio/ip/resolver_service.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/resolver_service.hpp @@ -19,6 +19,8 @@  #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/resolver_service.hpp>  #include <boost/asio/detail/service_base.hpp> @@ -49,10 +51,10 @@ public:    typedef typename InternetProtocol::endpoint endpoint_type;    /// The query type. -  typedef typename InternetProtocol::resolver_query query_type; +  typedef basic_resolver_query<InternetProtocol> query_type;    /// The iterator type. -  typedef typename InternetProtocol::resolver_iterator iterator_type; +  typedef basic_resolver_iterator<InternetProtocol> iterator_type;  private:    // The type of the platform-specific implementation. diff --git a/3rdParty/Boost/src/boost/asio/ip/tcp.hpp b/3rdParty/Boost/src/boost/asio/ip/tcp.hpp index a42c999..541c95c 100644 --- a/3rdParty/Boost/src/boost/asio/ip/tcp.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/tcp.hpp @@ -48,10 +48,10 @@ public:    /// The type of a TCP endpoint.    typedef basic_endpoint<tcp> endpoint; -  /// The type of a resolver query. +  /// (Deprecated: use resolver::query.) The type of a resolver query.    typedef basic_resolver_query<tcp> resolver_query; -  /// The type of a resolver iterator. +  /// (Deprecated: use resolver::iterator.) The type of a resolver iterator.    typedef basic_resolver_iterator<tcp> resolver_iterator;    /// Construct to represent the IPv4 TCP protocol. diff --git a/3rdParty/Boost/src/boost/asio/ip/udp.hpp b/3rdParty/Boost/src/boost/asio/ip/udp.hpp index e1793c7..e592e06 100644 --- a/3rdParty/Boost/src/boost/asio/ip/udp.hpp +++ b/3rdParty/Boost/src/boost/asio/ip/udp.hpp @@ -45,10 +45,10 @@ public:    /// The type of a UDP endpoint.    typedef basic_endpoint<udp> endpoint; -  /// The type of a resolver query. +  /// (Deprecated: use resolver::query.) The type of a resolver query.    typedef basic_resolver_query<udp> resolver_query; -  /// The type of a resolver iterator. +  /// (Deprecated: use resolver::iterator.) The type of a resolver iterator.    typedef basic_resolver_iterator<udp> resolver_iterator;    /// Construct to represent the IPv4 UDP protocol. diff --git a/3rdParty/Boost/src/boost/asio/posix/stream_descriptor_service.hpp b/3rdParty/Boost/src/boost/asio/posix/stream_descriptor_service.hpp index e64a617..89b9ef4 100644 --- a/3rdParty/Boost/src/boost/asio/posix/stream_descriptor_service.hpp +++ b/3rdParty/Boost/src/boost/asio/posix/stream_descriptor_service.hpp @@ -35,19 +35,7 @@  #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \    || defined(GENERATING_DOCUMENTATION) -#if defined(BOOST_ASIO_HAS_EPOLL) -# include <boost/asio/detail/epoll_reactor.hpp> -# include <boost/asio/detail/reactive_descriptor_service.hpp> -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include <boost/asio/detail/kqueue_reactor.hpp> -# include <boost/asio/detail/reactive_descriptor_service.hpp> -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include <boost/asio/detail/dev_poll_reactor.hpp> -# include <boost/asio/detail/reactive_descriptor_service.hpp> -#else -# include <boost/asio/detail/select_reactor.hpp> -# include <boost/asio/detail/reactive_descriptor_service.hpp> -#endif +#include <boost/asio/detail/reactive_descriptor_service.hpp>  namespace boost {  namespace asio { @@ -69,19 +57,7 @@ public:  private:    // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::reactive_descriptor_service< -      detail::epoll_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::reactive_descriptor_service< -      detail::kqueue_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -  typedef detail::reactive_descriptor_service< -      detail::dev_poll_reactor<false> > service_impl_type; -#else -  typedef detail::reactive_descriptor_service< -      detail::select_reactor<false> > service_impl_type; -#endif +  typedef detail::reactive_descriptor_service service_impl_type;  public:    /// The type of a stream descriptor implementation. @@ -101,13 +77,14 @@ public:    /// Construct a new stream descriptor service for the specified io_service.    explicit stream_descriptor_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<stream_descriptor_service>(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined descriptorr objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new stream descriptor implementation. @@ -196,8 +173,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace posix diff --git a/3rdParty/Boost/src/boost/asio/raw_socket_service.hpp b/3rdParty/Boost/src/boost/asio/raw_socket_service.hpp index 1b5c03c..23427d7 100644 --- a/3rdParty/Boost/src/boost/asio/raw_socket_service.hpp +++ b/3rdParty/Boost/src/boost/asio/raw_socket_service.hpp @@ -28,17 +28,7 @@  #if defined(BOOST_ASIO_HAS_IOCP)  # include <boost/asio/detail/win_iocp_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include <boost/asio/detail/epoll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include <boost/asio/detail/kqueue_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include <boost/asio/detail/dev_poll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp>  #else -# include <boost/asio/detail/select_reactor.hpp>  # include <boost/asio/detail/reactive_socket_service.hpp>  #endif @@ -70,18 +60,8 @@ private:    // The type of the platform-specific implementation.  #if defined(BOOST_ASIO_HAS_IOCP)    typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::reactive_socket_service< -      Protocol, detail::epoll_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::reactive_socket_service< -      Protocol, detail::kqueue_reactor<false> > service_impl_type; -#elif defined(BOOST_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; +  typedef detail::reactive_socket_service<Protocol> service_impl_type;  #endif  public: @@ -103,13 +83,14 @@ public:    explicit raw_socket_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<          raw_socket_service<Protocol> >(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new raw socket implementation. @@ -324,8 +305,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace asio diff --git a/3rdParty/Boost/src/boost/asio/read.hpp b/3rdParty/Boost/src/boost/asio/read.hpp index 8243d0f..40ccc00 100644 --- a/3rdParty/Boost/src/boost/asio/read.hpp +++ b/3rdParty/Boost/src/boost/asio/read.hpp @@ -301,7 +301,10 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. + * async_read_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other read operations (such + * as async_read, the stream's async_read_some function, or any other composed + * operations that perform reads) until this operation completes.   *   * @param s The stream from which the data is to be read. The type must support   * the AsyncReadStream concept. @@ -430,7 +433,10 @@ void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. + * async_read_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other read operations (such + * as async_read, the stream's async_read_some function, or any other composed + * operations that perform reads) until this operation completes.   *   * @param s The stream from which the data is to be read. The type must support   * the AsyncReadStream concept. @@ -477,7 +483,10 @@ void async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,   * @li The completion_condition function object returns 0.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. + * async_read_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other read operations (such + * as async_read, the stream's async_read_some function, or any other composed + * operations that perform reads) until this operation completes.   *   * @param s The stream from which the data is to be read. The type must support   * the AsyncReadStream concept. diff --git a/3rdParty/Boost/src/boost/asio/read_until.hpp b/3rdParty/Boost/src/boost/asio/read_until.hpp index 2f50072..ec6cb42 100644 --- a/3rdParty/Boost/src/boost/asio/read_until.hpp +++ b/3rdParty/Boost/src/boost/asio/read_until.hpp @@ -129,6 +129,16 @@ struct is_match_condition   * std::istream is(&b);   * std::string line;   * std::getline(is, line); @endcode + * After the @c read_until operation completes successfully, the buffer @c b + * contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode + * The call to @c std::getline then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\n' } @endcode + * The remaining data is left in the buffer @c b as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c read_until operation.   */  template <typename SyncReadStream, typename Allocator>  std::size_t read_until(SyncReadStream& s, @@ -206,6 +216,16 @@ std::size_t read_until(SyncReadStream& s,   * std::istream is(&b);   * std::string line;   * std::getline(is, line); @endcode + * After the @c read_until operation completes successfully, the buffer @c b + * contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c std::getline then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * The remaining data is left in the buffer @c b as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c read_until operation.   */  template <typename SyncReadStream, typename Allocator>  std::size_t read_until(SyncReadStream& s, @@ -285,6 +305,16 @@ std::size_t read_until(SyncReadStream& s,   * std::istream is(&b);   * std::string line;   * std::getline(is, line); @endcode + * After the @c read_until operation completes successfully, the buffer @c b + * contains the data which matched the regular expression: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c std::getline then extracts the data up to and including the + * match, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * The remaining data is left in the buffer @c b as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c read_until operation.   */  template <typename SyncReadStream, typename Allocator>  std::size_t read_until(SyncReadStream& s, @@ -511,8 +541,12 @@ std::size_t read_until(SyncReadStream& s,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. + * async_read_some function, and is known as a <em>composed operation</em>. If + * the streambuf's get area already contains the delimiter, this asynchronous + * operation completes immediately. The program must ensure that the stream + * performs no other read operations (such as async_read, async_read_until, the + * stream's async_read_some function, or any other composed operations that + * perform reads) until this operation completes.   *   * @param s The stream from which the data is to be read. The type must support   * the AsyncReadStream concept. @@ -561,6 +595,16 @@ std::size_t read_until(SyncReadStream& s,   * }   * ...   * boost::asio::async_read_until(s, b, '\n', handler); @endcode + * After the @c async_read_until operation completes successfully, the buffer + * @c b contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode + * The call to @c std::getline then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\n' } @endcode + * The remaining data is left in the buffer @c b as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c async_read_until operation.   */  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>  void async_read_until(AsyncReadStream& s, @@ -580,8 +624,12 @@ void async_read_until(AsyncReadStream& s,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. + * async_read_some function, and is known as a <em>composed operation</em>. If + * the streambuf's get area already contains the delimiter, this asynchronous + * operation completes immediately. The program must ensure that the stream + * performs no other read operations (such as async_read, async_read_until, the + * stream's async_read_some function, or any other composed operations that + * perform reads) until this operation completes.   *   * @param s The stream from which the data is to be read. The type must support   * the AsyncReadStream concept. @@ -630,6 +678,16 @@ void async_read_until(AsyncReadStream& s,   * }   * ...   * boost::asio::async_read_until(s, b, "\r\n", handler); @endcode + * After the @c async_read_until operation completes successfully, the buffer + * @c b contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c std::getline then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * The remaining data is left in the buffer @c b as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c async_read_until operation.   */  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>  void async_read_until(AsyncReadStream& s, @@ -650,8 +708,13 @@ void async_read_until(AsyncReadStream& s,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains data - * that matches the regular expression, the function returns immediately. + * async_read_some function, and is known as a <em>composed operation</em>. If + * the streambuf's get area already contains data that matches the regular + * expression, this asynchronous operation completes immediately. The program + * must ensure that the stream performs no other read operations (such as + * async_read, async_read_until, the stream's async_read_some function, or any + * other composed operations that perform reads) until this operation + * completes.   *   * @param s The stream from which the data is to be read. The type must support   * the AsyncReadStream concept. @@ -702,6 +765,16 @@ void async_read_until(AsyncReadStream& s,   * }   * ...   * boost::asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode + * After the @c async_read_until operation completes successfully, the buffer + * @c b contains the data which matched the regular expression: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c std::getline then extracts the data up to and including the + * match, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * The remaining data is left in the buffer @c b as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c async_read_until operation.   */  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>  void async_read_until(AsyncReadStream& s, @@ -723,8 +796,12 @@ void async_read_until(AsyncReadStream& s,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the match condition function object already - * indicates a match, the operation completes immediately. + * async_read_some function, and is known as a <em>composed operation</em>. If + * the match condition function object already indicates a match, this + * asynchronous operation completes immediately. The program must ensure that + * the stream performs no other read operations (such as async_read, + * async_read_until, the stream's async_read_some function, or any other + * composed operations that perform reads) until this operation completes.   *   * @param s The stream from which the data is to be read. The type must support   * the AsyncReadStream concept. diff --git a/3rdParty/Boost/src/boost/asio/serial_port_service.hpp b/3rdParty/Boost/src/boost/asio/serial_port_service.hpp index 3abd244..f1a2344 100644 --- a/3rdParty/Boost/src/boost/asio/serial_port_service.hpp +++ b/3rdParty/Boost/src/boost/asio/serial_port_service.hpp @@ -54,18 +54,8 @@ private:    // The type of the platform-specific implementation.  #if defined(BOOST_ASIO_HAS_IOCP)    typedef detail::win_iocp_serial_port_service service_impl_type; -#elif defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::reactive_serial_port_service< -      detail::epoll_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::reactive_serial_port_service< -      detail::kqueue_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -  typedef detail::reactive_serial_port_service< -      detail::dev_poll_reactor<false> > service_impl_type;  #else -  typedef detail::reactive_serial_port_service< -      detail::select_reactor<false> > service_impl_type; +  typedef detail::reactive_serial_port_service service_impl_type;  #endif  public: @@ -86,13 +76,14 @@ public:    /// Construct a new serial port service for the specified io_service.    explicit serial_port_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<serial_port_service>(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new serial port implementation. @@ -203,8 +194,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace asio diff --git a/3rdParty/Boost/src/boost/asio/socket_acceptor_service.hpp b/3rdParty/Boost/src/boost/asio/socket_acceptor_service.hpp index edca5b7..184580f 100644 --- a/3rdParty/Boost/src/boost/asio/socket_acceptor_service.hpp +++ b/3rdParty/Boost/src/boost/asio/socket_acceptor_service.hpp @@ -24,17 +24,7 @@  #if defined(BOOST_ASIO_HAS_IOCP)  # include <boost/asio/detail/win_iocp_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include <boost/asio/detail/epoll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include <boost/asio/detail/kqueue_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include <boost/asio/detail/dev_poll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp>  #else -# include <boost/asio/detail/select_reactor.hpp>  # include <boost/asio/detail/reactive_socket_service.hpp>  #endif @@ -66,18 +56,8 @@ private:    // The type of the platform-specific implementation.  #if defined(BOOST_ASIO_HAS_IOCP)    typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::reactive_socket_service< -      Protocol, detail::epoll_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::reactive_socket_service< -      Protocol, detail::kqueue_reactor<false> > service_impl_type; -#elif defined(BOOST_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; +  typedef detail::reactive_socket_service<Protocol> service_impl_type;  #endif  public: @@ -99,13 +79,14 @@ public:    explicit socket_acceptor_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<          socket_acceptor_service<Protocol> >(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new socket acceptor implementation. @@ -226,8 +207,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace asio diff --git a/3rdParty/Boost/src/boost/asio/stream_socket_service.hpp b/3rdParty/Boost/src/boost/asio/stream_socket_service.hpp index 6a8dd36..15aa683 100644 --- a/3rdParty/Boost/src/boost/asio/stream_socket_service.hpp +++ b/3rdParty/Boost/src/boost/asio/stream_socket_service.hpp @@ -28,17 +28,7 @@  #if defined(BOOST_ASIO_HAS_IOCP)  # include <boost/asio/detail/win_iocp_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_EPOLL) -# include <boost/asio/detail/epoll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_KQUEUE) -# include <boost/asio/detail/kqueue_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_DEV_POLL) -# include <boost/asio/detail/dev_poll_reactor.hpp> -# include <boost/asio/detail/reactive_socket_service.hpp>  #else -# include <boost/asio/detail/select_reactor.hpp>  # include <boost/asio/detail/reactive_socket_service.hpp>  #endif @@ -70,18 +60,8 @@ private:    // The type of the platform-specific implementation.  #if defined(BOOST_ASIO_HAS_IOCP)    typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_EPOLL) -  typedef detail::reactive_socket_service< -      Protocol, detail::epoll_reactor<false> > service_impl_type; -#elif defined(BOOST_ASIO_HAS_KQUEUE) -  typedef detail::reactive_socket_service< -      Protocol, detail::kqueue_reactor<false> > service_impl_type; -#elif defined(BOOST_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; +  typedef detail::reactive_socket_service<Protocol> service_impl_type;  #endif  public: @@ -103,13 +83,14 @@ public:    explicit stream_socket_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<          stream_socket_service<Protocol> >(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new stream socket implementation. @@ -287,8 +268,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace asio diff --git a/3rdParty/Boost/src/boost/asio/version.hpp b/3rdParty/Boost/src/boost/asio/version.hpp index 67e9171..0172f73 100644 --- a/3rdParty/Boost/src/boost/asio/version.hpp +++ b/3rdParty/Boost/src/boost/asio/version.hpp @@ -18,6 +18,6 @@  // BOOST_ASIO_VERSION % 100 is the sub-minor version  // BOOST_ASIO_VERSION / 100 % 1000 is the minor version  // BOOST_ASIO_VERSION / 100000 is the major version -#define BOOST_ASIO_VERSION 100404 // 1.4.4 +#define BOOST_ASIO_VERSION 100405 // 1.4.5  #endif // BOOST_ASIO_VERSION_HPP diff --git a/3rdParty/Boost/src/boost/asio/windows/random_access_handle_service.hpp b/3rdParty/Boost/src/boost/asio/windows/random_access_handle_service.hpp index fbbde67..1dcbee4 100644 --- a/3rdParty/Boost/src/boost/asio/windows/random_access_handle_service.hpp +++ b/3rdParty/Boost/src/boost/asio/windows/random_access_handle_service.hpp @@ -78,13 +78,14 @@ public:    explicit random_access_handle_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<          random_access_handle_service>(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new random-access handle implementation. @@ -165,8 +166,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace windows diff --git a/3rdParty/Boost/src/boost/asio/windows/stream_handle_service.hpp b/3rdParty/Boost/src/boost/asio/windows/stream_handle_service.hpp index c2224e4..cc6c6e8 100644 --- a/3rdParty/Boost/src/boost/asio/windows/stream_handle_service.hpp +++ b/3rdParty/Boost/src/boost/asio/windows/stream_handle_service.hpp @@ -76,13 +76,14 @@ public:    /// Construct a new stream handle service for the specified io_service.    explicit stream_handle_service(boost::asio::io_service& io_service)      : boost::asio::detail::service_base<stream_handle_service>(io_service), -      service_impl_(boost::asio::use_service<service_impl_type>(io_service)) +      service_impl_(io_service)    {    }    /// Destroy all user-defined handler objects owned by the service.    void shutdown_service()    { +    service_impl_.shutdown_service();    }    /// Construct a new stream handle implementation. @@ -163,8 +164,8 @@ public:    }  private: -  // The service that provides the platform-specific implementation. -  service_impl_type& service_impl_; +  // The platform-specific implementation. +  service_impl_type service_impl_;  };  } // namespace windows diff --git a/3rdParty/Boost/src/boost/asio/write.hpp b/3rdParty/Boost/src/boost/asio/write.hpp index 2b9d4b7..2a95735 100644 --- a/3rdParty/Boost/src/boost/asio/write.hpp +++ b/3rdParty/Boost/src/boost/asio/write.hpp @@ -306,7 +306,10 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_write_some function. + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes.   *   * @param s The stream to which the data is to be written. The type must support   * the AsyncWriteStream concept. @@ -360,7 +363,10 @@ void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,   * @li The completion_condition function object returns 0.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_write_some function. + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes.   *   * @param s The stream to which the data is to be written. The type must support   * the AsyncWriteStream concept. @@ -430,7 +436,10 @@ void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,   * @li An error occurred.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_write_some function. + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes.   *   * @param s The stream to which the data is to be written. The type must support   * the AsyncWriteStream concept. @@ -472,7 +481,10 @@ void async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,   * @li The completion_condition function object returns 0.   *   * This operation is implemented in terms of zero or more calls to the stream's - * async_write_some function. + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes.   *   * @param s The stream to which the data is to be written. The type must support   * the AsyncWriteStream concept. diff --git a/3rdParty/Boost/src/boost/concept/detail/has_constraints.hpp b/3rdParty/Boost/src/boost/concept/detail/has_constraints.hpp index 3112b55..9191181 100644 --- a/3rdParty/Boost/src/boost/concept/detail/has_constraints.hpp +++ b/3rdParty/Boost/src/boost/concept/detail/has_constraints.hpp @@ -19,7 +19,7 @@ namespace detail    template <class Model, void (Model::*)()>    struct wrap_constraints {}; -#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) || defined(__CUDACC__)    // Work around the following bogus error in Sun Studio 11, by    // turning off the has_constraints function entirely:    //    Error: complex expression not allowed in dependent template diff --git a/3rdParty/Boost/src/boost/concept_check.hpp b/3rdParty/Boost/src/boost/concept_check.hpp index 12ec2ad..7ee3036 100644 --- a/3rdParty/Boost/src/boost/concept_check.hpp +++ b/3rdParty/Boost/src/boost/concept_check.hpp @@ -330,7 +330,16 @@ namespace boost        {            f(arg);        } -       + +#if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ +                      && BOOST_WORKAROUND(__GNUC__, > 3))) +      // Declare a dummy construktor to make gcc happy. +      // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. +      // (warning: non-static reference "const double& boost::UnaryFunction<YourClassHere>::arg" +      // in class without a constructor [-Wuninitialized]) +      UnaryFunction(); +#endif +        Func f;        Arg arg;    }; diff --git a/3rdParty/Boost/src/boost/config/compiler/gcc.hpp b/3rdParty/Boost/src/boost/config/compiler/gcc.hpp index 6cae94c..fe2c52e 100644 --- a/3rdParty/Boost/src/boost/config/compiler/gcc.hpp +++ b/3rdParty/Boost/src/boost/config/compiler/gcc.hpp @@ -108,11 +108,8 @@  //  #define BOOST_NO_CONSTEXPR  #define BOOST_NO_EXTERN_TEMPLATE -#define BOOST_NO_LAMBDAS  #define BOOST_NO_NULLPTR -#define BOOST_NO_RAW_LITERALS  #define BOOST_NO_TEMPLATE_ALIASES -#define BOOST_NO_UNICODE_LITERALS  // C++0x features in 4.3.n and later  // @@ -168,6 +165,9 @@  //  #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)  #  define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS +#  define BOOST_NO_LAMBDAS +#  define BOOST_NO_RAW_LITERALS +#  define BOOST_NO_UNICODE_LITERALS  #endif  // ConceptGCC compiler: diff --git a/3rdParty/Boost/src/boost/config/compiler/nvcc.hpp b/3rdParty/Boost/src/boost/config/compiler/nvcc.hpp new file mode 100644 index 0000000..7d831af --- /dev/null +++ b/3rdParty/Boost/src/boost/config/compiler/nvcc.hpp @@ -0,0 +1,85 @@ +//  (C) Copyright Eric Jourdanneau, Joel Falcou 2010 +//  Use, modification and distribution are subject to 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) + +//  See http://www.boost.org for most recent version. + +//  NVIDIA CUDA C++ compiler setup + +#ifndef BOOST_COMPILER +#  define BOOST_COMPILER "NVIDIA CUDA C++ Compiler" +#endif + +// NVIDIA Specific support +// BOOST_GPU_ENABLED : Flag a function or a method as being enabled on the host and device +#define BOOST_GPU_ENABLED __host__ __device__ + +// Boost support macro for NVCC  +// NVCC Basically behaves like some flavor of MSVC6 + some specific quirks +#define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +#define BOOST_MSVC6_MEMBER_TEMPLATES +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_STDINT_H +#define BOOST_HAS_SIGACTION +#define BOOST_HAS_SCHED_YIELD +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_PTHREAD_YIELD +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#define BOOST_HAS_NRVO +#define BOOST_HAS_NL_TYPES_H +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_LONG_LONG +#define BOOST_HAS_LOG1P +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_CLOCK_GETTIME +#define BOOST_NO_VARIADIC_TEMPLATES +#define BOOST_NO_UNICODE_LITERALS +#define BOOST_NO_TEMPLATE_ALIASES +#define BOOST_NO_STD_UNORDERED +#define BOOST_NO_STATIC_ASSERT +#define BOOST_NO_SFINAE_EXPR +#define BOOST_NO_SCOPED_ENUMS +#define BOOST_NO_RVALUE_REFERENCES +#define BOOST_NO_RAW_LITERALS +#define BOOST_NO_NULLPTR +#define BOOST_NO_LAMBDAS +#define BOOST_NO_INITIALIZER_LISTS +#define BOOST_NO_MS_INT64_NUMERIC_LIMITS +#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS +#define BOOST_NO_EXTERN_TEMPLATE +#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS +#define BOOST_NO_DELETED_FUNCTIONS +#define BOOST_NO_DEFAULTED_FUNCTIONS +#define BOOST_NO_DECLTYPE +#define BOOST_NO_CONSTEXPR +#define BOOST_NO_CONCEPTS +#define BOOST_NO_CHAR32_T +#define BOOST_NO_CHAR16_T +#define BOOST_NO_AUTO_MULTIDECLARATIONS +#define BOOST_NO_AUTO_DECLARATIONS +#define BOOST_NO_0X_HDR_UNORDERED_SET +#define BOOST_NO_0X_HDR_UNORDERED_MAP +#define BOOST_NO_0X_HDR_TYPE_TRAITS +#define BOOST_NO_0X_HDR_TUPLE +#define BOOST_NO_0X_HDR_THREAD +#define BOOST_NO_0X_HDR_SYSTEM_ERROR +#define BOOST_NO_0X_HDR_REGEX +#define BOOST_NO_0X_HDR_RATIO +#define BOOST_NO_0X_HDR_RANDOM +#define BOOST_NO_0X_HDR_MUTEX +#define BOOST_NO_0X_HDR_MEMORY_CONCEPTS +#define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS +#define BOOST_NO_0X_HDR_INITIALIZER_LIST +#define BOOST_NO_0X_HDR_FUTURE +#define BOOST_NO_0X_HDR_FORWARD_LIST +#define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS +#define BOOST_NO_0X_HDR_CONDITION_VARIABLE +#define BOOST_NO_0X_HDR_CONCEPTS +#define BOOST_NO_0X_HDR_CODECVT +#define BOOST_NO_0X_HDR_CHRONO +#define BOOST_NO_0X_HDR_ARRAY + diff --git a/3rdParty/Boost/src/boost/config/compiler/pgi.hpp b/3rdParty/Boost/src/boost/config/compiler/pgi.hpp index e40553e..1c7c84b 100644 --- a/3rdParty/Boost/src/boost/config/compiler/pgi.hpp +++ b/3rdParty/Boost/src/boost/config/compiler/pgi.hpp @@ -16,11 +16,28 @@  // if no threading API is detected.  // -#if (__PGIC__ >= 7) +// PGI 10.x doesn't seem to define __PGIC__ + +// versions earlier than 10.x do define __PGIC__ +#if __PGIC__ >= 10 + +// options requested by configure --enable-test +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_NRVO +#define BOOST_HAS_LONG_LONG + +// options --enable-test wants undefined +#undef BOOST_NO_STDC_NAMESPACE +#undef BOOST_NO_EXCEPTION_STD_NAMESPACE +#undef BOOST_DEDUCED_TYPENAME + +#elif __PGIC__ >= 7  #define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL   #define BOOST_NO_TWO_PHASE_NAME_LOOKUP  #define BOOST_NO_SWPRINTF +#define BOOST_NO_AUTO_MULTIDECLARATIONS +#define BOOST_NO_AUTO_DECLARATIONS  #else @@ -32,8 +49,6 @@  //  //   See boost\config\suffix.hpp for BOOST_NO_LONG_LONG  // -#define BOOST_NO_AUTO_DECLARATIONS -#define BOOST_NO_AUTO_MULTIDECLARATIONS  #define BOOST_NO_CHAR16_T  #define BOOST_NO_CHAR32_T  #define BOOST_NO_CONCEPTS diff --git a/3rdParty/Boost/src/boost/config/compiler/visualc.hpp b/3rdParty/Boost/src/boost/config/compiler/visualc.hpp index 990901f..f8cc109 100644 --- a/3rdParty/Boost/src/boost/config/compiler/visualc.hpp +++ b/3rdParty/Boost/src/boost/config/compiler/visualc.hpp @@ -125,7 +125,7 @@  #if (_MSC_VER >= 1200)  #   define BOOST_HAS_MS_INT64  #endif -#if (_MSC_VER >= 1310) && (defined(_MSC_EXTENSIONS) || (_MSC_VER >= 1500)) +#if (_MSC_VER >= 1310) && (defined(_MSC_EXTENSIONS) || (_MSC_VER >= 1400))  #   define BOOST_HAS_LONG_LONG  #else  #   define BOOST_NO_LONG_LONG diff --git a/3rdParty/Boost/src/boost/config/platform/symbian.hpp b/3rdParty/Boost/src/boost/config/platform/symbian.hpp new file mode 100644 index 0000000..ad37943 --- /dev/null +++ b/3rdParty/Boost/src/boost/config/platform/symbian.hpp @@ -0,0 +1,94 @@ +//  (C) Copyright Yuriy Krasnoschek 2009.  +//  (C) Copyright John Maddock 2001 - 2003.  +//  (C) Copyright Jens Maurer 2001 - 2003.  +//  Use, modification and distribution are subject to 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) + +//  See http://www.boost.org for most recent version. + +//  symbian specific config options: + + +#define BOOST_PLATFORM "Symbian" +#define BOOST_SYMBIAN 1 + + +#if defined(__S60_3X__) +// Open C / C++ plugin was introdused in this SDK, earlier versions don't have CRT / STL +#  define BOOST_S60_3rd_EDITION_FP2_OR_LATER_SDK +// make sure we have __GLIBC_PREREQ if available at all +#  include <cstdlib> +// boilerplate code: +#  define BOOST_HAS_UNISTD_H +#  include <boost/config/posix_features.hpp> +// S60 SDK defines _POSIX_VERSION as POSIX.1 +#  ifndef BOOST_HAS_STDINT_H +#    define BOOST_HAS_STDINT_H +#  endif +#  ifndef BOOST_HAS_GETTIMEOFDAY +#    define BOOST_HAS_GETTIMEOFDAY +#  endif +#  ifndef BOOST_HAS_DIRENT_H +#    define BOOST_HAS_DIRENT_H +#  endif +#  ifndef BOOST_HAS_SIGACTION +#    define BOOST_HAS_SIGACTION +#  endif +#  ifndef BOOST_HAS_PTHREADS +#    define BOOST_HAS_PTHREADS +#  endif +#  ifndef BOOST_HAS_NANOSLEEP +#    define BOOST_HAS_NANOSLEEP +#  endif +#  ifndef BOOST_HAS_SCHED_YIELD +#    define BOOST_HAS_SCHED_YIELD +#  endif +#  ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#    define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#  endif +#  ifndef BOOST_HAS_LOG1P +#    define BOOST_HAS_LOG1P +#  endif +#  ifndef BOOST_HAS_EXPM1 +#    define BOOST_HAS_EXPM1 +#  endif +#  ifndef BOOST_POSIX_API +#    define BOOST_POSIX_API +#  endif +// endianess support +#  include <sys/endian.h> +// Symbian SDK provides _BYTE_ORDER instead of __BYTE_ORDER +#  ifndef __LITTLE_ENDIAN +#    ifdef _LITTLE_ENDIAN +#      define __LITTLE_ENDIAN _LITTLE_ENDIAN +#    else +#      define __LITTLE_ENDIAN 1234 +#    endif +#  endif +#  ifndef __BIG_ENDIAN +#    ifdef _BIG_ENDIAN +#      define __BIG_ENDIAN _BIG_ENDIAN +#    else +#      define __BIG_ENDIAN 4321 +#    endif +#  endif +#  ifndef __BYTE_ORDER +#    define __BYTE_ORDER __LITTLE_ENDIAN // Symbian is LE +#  endif +// Known limitations +#  define BOOST_ASIO_DISABLE_SERIAL_PORT +#  define BOOST_DATE_TIME_NO_LOCALE +#  define BOOST_NO_STD_WSTRING +#  define BOOST_EXCEPTION_DISABLE +#  define BOOST_NO_EXCEPTIONS + +#else // TODO: More platform support e.g. UIQ +#  error "Unsuppoted Symbian SDK" +#endif + +#if defined(__WINSCW__) && !defined(BOOST_DISABLE_WIN32) +#  define BOOST_DISABLE_WIN32 // winscw defines WIN32 macro +#endif + + diff --git a/3rdParty/Boost/src/boost/config/select_compiler_config.hpp b/3rdParty/Boost/src/boost/config/select_compiler_config.hpp index 9141cd6..792963e 100644 --- a/3rdParty/Boost/src/boost/config/select_compiler_config.hpp +++ b/3rdParty/Boost/src/boost/config/select_compiler_config.hpp @@ -31,6 +31,7 @@  #   define BOOST_CXX_IBMCPP   0  #   define BOOST_CXX_MSVC     0  #   define BOOST_CXX_PGI      0 +#   define BOOST_CXX_NVCC     0  // locate which compiler we are using and define @@ -40,6 +41,10 @@  // GCC-XML emulates other compilers, it has to appear first here!  #   define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc_xml.hpp" +#elif defined __CUDACC__ +//  NVIDIA CUDA C++ compiler for GPU +#   define BOOST_COMPILER_CONFIG "boost/config/compiler/nvcc.hpp" +  #elif defined __COMO__  //  Comeau C++  #   define BOOST_COMPILER_CONFIG "boost/config/compiler/comeau.hpp" diff --git a/3rdParty/Boost/src/boost/config/select_platform_config.hpp b/3rdParty/Boost/src/boost/config/select_platform_config.hpp index 615bb06..8606e12 100644 --- a/3rdParty/Boost/src/boost/config/select_platform_config.hpp +++ b/3rdParty/Boost/src/boost/config/select_platform_config.hpp @@ -65,6 +65,10 @@  // vxWorks:  #  define BOOST_PLATFORM_CONFIG "boost/config/platform/vxworks.hpp" +#elif defined(__SYMBIAN32__)  +// Symbian:  +#  define BOOST_PLATFORM_CONFIG "boost/config/platform/symbian.hpp"  +  #else  #  if defined(unix) \ diff --git a/3rdParty/Boost/src/boost/config/suffix.hpp b/3rdParty/Boost/src/boost/config/suffix.hpp index fa44986..9e4d078 100644 --- a/3rdParty/Boost/src/boost/config/suffix.hpp +++ b/3rdParty/Boost/src/boost/config/suffix.hpp @@ -8,7 +8,7 @@  //  Copyright (c) 2002-2003 David Abrahams  //  Copyright (c) 2003 Gennaro Prota  //  Copyright (c) 2003 Eric Friedman -// +//  Copyright (c) 2010 Eric Jourdanneau, Joel Falcou  // 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) @@ -596,6 +596,11 @@ namespace boost{  #     endif  #  endif +// +// Set some default values GPU support +// +#  ifndef BOOST_GPU_ENABLED +#  define BOOST_GPU_ENABLED  +#  endif  #endif - diff --git a/3rdParty/Boost/src/boost/cstdlib.hpp b/3rdParty/Boost/src/boost/cstdlib.hpp deleted file mode 100644 index 6322146..0000000 --- a/3rdParty/Boost/src/boost/cstdlib.hpp +++ /dev/null @@ -1,41 +0,0 @@ -//  boost/cstdlib.hpp header  ------------------------------------------------// - -//  Copyright Beman Dawes 2001.  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) - -//  See http://www.boost.org/libs/utility/cstdlib.html for documentation. - -//  Revision History -//   26 Feb 01  Initial version (Beman Dawes) - -#ifndef BOOST_CSTDLIB_HPP -#define BOOST_CSTDLIB_HPP - -#include <cstdlib> - -namespace boost -{ -   //  The intent is to propose the following for addition to namespace std -   //  in the C++ Standard Library, and to then deprecate EXIT_SUCCESS and -   //  EXIT_FAILURE.  As an implementation detail, this header defines the -   //  new constants in terms of EXIT_SUCCESS and EXIT_FAILURE.  In a new -   //  standard, the constants would be implementation-defined, although it -   //  might be worthwhile to "suggest" (which a standard is allowed to do) -   //  values of 0 and 1 respectively. - -   //  Rationale for having multiple failure values: some environments may -   //  wish to distinguish between different classes of errors. -   //  Rationale for choice of values: programs often use values < 100 for -   //  their own error reporting.  Values > 255 are sometimes reserved for -   //  system detected errors.  200/201 were suggested to minimize conflict. - -   const int exit_success = EXIT_SUCCESS;  // implementation-defined value -   const int exit_failure = EXIT_FAILURE;  // implementation-defined value -   const int exit_exception_failure = 200; // otherwise uncaught exception -   const int exit_test_failure = 201;      // report_error or -                                           //  report_critical_error called. -} - -#endif - diff --git a/3rdParty/Boost/src/boost/date_time/gregorian/conversion.hpp b/3rdParty/Boost/src/boost/date_time/gregorian/conversion.hpp index 6d4b606..f35796e 100644 --- a/3rdParty/Boost/src/boost/date_time/gregorian/conversion.hpp +++ b/3rdParty/Boost/src/boost/date_time/gregorian/conversion.hpp @@ -15,7 +15,6 @@  #include <boost/date_time/c_time.hpp>  #include <boost/date_time/special_defs.hpp>  #include <boost/date_time/gregorian/gregorian_types.hpp> -#include <cstring>  namespace boost { @@ -42,8 +41,7 @@ namespace gregorian {          boost::throw_exception(std::out_of_range(s));      } -    std::tm datetm; -    memset(&datetm, 0, sizeof(std::tm)); +    std::tm datetm = {}; // zero initialization is needed for extension members, like tm_zone      boost::gregorian::date::ymd_type ymd = d.year_month_day();      datetm.tm_year = ymd.year - 1900;      datetm.tm_mon = ymd.month - 1; diff --git a/3rdParty/Boost/src/boost/date_time/posix_time/conversion.hpp b/3rdParty/Boost/src/boost/date_time/posix_time/conversion.hpp index a7b1a80..9cdb864 100644 --- a/3rdParty/Boost/src/boost/date_time/posix_time/conversion.hpp +++ b/3rdParty/Boost/src/boost/date_time/posix_time/conversion.hpp @@ -15,7 +15,6 @@  #include <boost/date_time/c_time.hpp>  #include <boost/date_time/time_resolution_traits.hpp> // absolute_value  #include <boost/date_time/gregorian/conversion.hpp> -#include <cstring>  namespace boost { @@ -44,8 +43,7 @@ namespace posix_time {    //! Convert a time_duration to a tm structure truncating any fractional seconds and zeroing fields for date components    inline    std::tm to_tm(const boost::posix_time::time_duration& td) { -    std::tm timetm; -    memset(&timetm, 0, sizeof(std::tm)); +    std::tm timetm = {};      timetm.tm_hour = date_time::absolute_value(td.hours());      timetm.tm_min = date_time::absolute_value(td.minutes());      timetm.tm_sec = date_time::absolute_value(td.seconds()); diff --git a/3rdParty/Boost/src/boost/detail/binary_search.hpp b/3rdParty/Boost/src/boost/detail/binary_search.hpp deleted file mode 100644 index 3dca9b6..0000000 --- a/3rdParty/Boost/src/boost/detail/binary_search.hpp +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c)  2000 David Abrahams.  -// 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) -//  -// Copyright (c) 1994 -// Hewlett-Packard Company -//  -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation.  Hewlett-Packard Company makes no -// representations about the suitability of this software for any -// purpose.  It is provided "as is" without express or implied warranty. -//  -// Copyright (c) 1996 -// Silicon Graphics Computer Systems, Inc. -//  -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation.  Silicon Graphics makes no -// representations about the suitability of this software for any -// purpose.  It is provided "as is" without express or implied warranty. -//  -#ifndef BINARY_SEARCH_DWA_122600_H_ -# define BINARY_SEARCH_DWA_122600_H_ - -# include <boost/detail/iterator.hpp> -# include <utility> - -namespace boost { namespace detail { - -template <class ForwardIter, class Tp> -ForwardIter lower_bound(ForwardIter first, ForwardIter last, -                             const Tp& val)  -{ -    typedef detail::iterator_traits<ForwardIter> traits; -     -    typename traits::difference_type len = boost::detail::distance(first, last); -    typename traits::difference_type half; -    ForwardIter middle; - -    while (len > 0) { -      half = len >> 1; -      middle = first; -      std::advance(middle, half); -      if (*middle < val) { -        first = middle; -        ++first; -        len = len - half - 1; -      } -      else -        len = half; -    } -    return first; -} - -template <class ForwardIter, class Tp, class Compare> -ForwardIter lower_bound(ForwardIter first, ForwardIter last, -                              const Tp& val, Compare comp) -{ -  typedef detail::iterator_traits<ForwardIter> traits; - -  typename traits::difference_type len = boost::detail::distance(first, last); -  typename traits::difference_type half; -  ForwardIter middle; - -  while (len > 0) { -    half = len >> 1; -    middle = first; -    std::advance(middle, half); -    if (comp(*middle, val)) { -      first = middle; -      ++first; -      len = len - half - 1; -    } -    else -      len = half; -  } -  return first; -} - -template <class ForwardIter, class Tp> -ForwardIter upper_bound(ForwardIter first, ForwardIter last, -                           const Tp& val) -{ -  typedef detail::iterator_traits<ForwardIter> traits; - -  typename traits::difference_type len = boost::detail::distance(first, last); -  typename traits::difference_type half; -  ForwardIter middle; - -  while (len > 0) { -    half = len >> 1; -    middle = first; -    std::advance(middle, half); -    if (val < *middle) -      len = half; -    else { -      first = middle; -      ++first; -      len = len - half - 1; -    } -  } -  return first; -} - -template <class ForwardIter, class Tp, class Compare> -ForwardIter upper_bound(ForwardIter first, ForwardIter last, -                           const Tp& val, Compare comp) -{ -  typedef detail::iterator_traits<ForwardIter> traits; - -  typename traits::difference_type len = boost::detail::distance(first, last); -  typename traits::difference_type half; -  ForwardIter middle; - -  while (len > 0) { -    half = len >> 1; -    middle = first; -    std::advance(middle, half); -    if (comp(val, *middle)) -      len = half; -    else { -      first = middle; -      ++first; -      len = len - half - 1; -    } -  } -  return first; -} - -template <class ForwardIter, class Tp> -std::pair<ForwardIter, ForwardIter> -equal_range(ForwardIter first, ForwardIter last, const Tp& val) -{ -  typedef detail::iterator_traits<ForwardIter> traits; - -  typename traits::difference_type len = boost::detail::distance(first, last); -  typename traits::difference_type half; -  ForwardIter middle, left, right; - -  while (len > 0) { -    half = len >> 1; -    middle = first; -    std::advance(middle, half); -    if (*middle < val) { -      first = middle; -      ++first; -      len = len - half - 1; -    } -    else if (val < *middle) -      len = half; -    else { -      left = boost::detail::lower_bound(first, middle, val); -      std::advance(first, len); -      right = boost::detail::upper_bound(++middle, first, val); -      return std::pair<ForwardIter, ForwardIter>(left, right); -    } -  } -  return std::pair<ForwardIter, ForwardIter>(first, first); -} - -template <class ForwardIter, class Tp, class Compare> -std::pair<ForwardIter, ForwardIter> -equal_range(ForwardIter first, ForwardIter last, const Tp& val, -              Compare comp) -{ -  typedef detail::iterator_traits<ForwardIter> traits; - -  typename traits::difference_type len = boost::detail::distance(first, last); -  typename traits::difference_type half; -  ForwardIter middle, left, right; - -  while (len > 0) { -    half = len >> 1; -    middle = first; -    std::advance(middle, half); -    if (comp(*middle, val)) { -      first = middle; -      ++first; -      len = len - half - 1; -    } -    else if (comp(val, *middle)) -      len = half; -    else { -      left = boost::detail::lower_bound(first, middle, val, comp); -      std::advance(first, len); -      right = boost::detail::upper_bound(++middle, first, val, comp); -      return std::pair<ForwardIter, ForwardIter>(left, right); -    } -  } -  return std::pair<ForwardIter, ForwardIter>(first, first); -}            - -template <class ForwardIter, class Tp> -bool binary_search(ForwardIter first, ForwardIter last, -                   const Tp& val) { -  ForwardIter i = boost::detail::lower_bound(first, last, val); -  return i != last && !(val < *i); -} - -template <class ForwardIter, class Tp, class Compare> -bool binary_search(ForwardIter first, ForwardIter last, -                   const Tp& val, -                   Compare comp) { -  ForwardIter i = boost::detail::lower_bound(first, last, val, comp); -  return i != last && !comp(val, *i); -} - -}} // namespace boost::detail - -#endif // BINARY_SEARCH_DWA_122600_H_ diff --git a/3rdParty/Boost/src/boost/detail/container_fwd.hpp b/3rdParty/Boost/src/boost/detail/container_fwd.hpp index bc7f780..67c5a21 100644 --- a/3rdParty/Boost/src/boost/detail/container_fwd.hpp +++ b/3rdParty/Boost/src/boost/detail/container_fwd.hpp @@ -13,7 +13,9 @@  #include <boost/config.hpp>  #include <boost/detail/workaround.hpp> -#if ((defined(__GLIBCPP__) || defined(__GLIBCXX__)) && defined(_GLIBCXX_DEBUG)) \ +#if defined(BOOST_DETAIL_NO_CONTAINER_FWD) \ +    || ((defined(__GLIBCPP__) || defined(__GLIBCXX__)) \ +        && (defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL))) \      || BOOST_WORKAROUND(__BORLANDC__, > 0x551) \      || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x842)) \      || (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) diff --git a/3rdParty/Boost/src/boost/detail/lcast_precision.hpp b/3rdParty/Boost/src/boost/detail/lcast_precision.hpp index d40ca21..93abce1 100644 --- a/3rdParty/Boost/src/boost/detail/lcast_precision.hpp +++ b/3rdParty/Boost/src/boost/detail/lcast_precision.hpp @@ -173,8 +173,8 @@ inline void lcast_set_precision(std::ios_base& stream, T*)  template<class Source, class Target>  inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)  { -    std::streamsize const s = lcast_get_precision((Source*)0); -    std::streamsize const t = lcast_get_precision((Target*)0); +    std::streamsize const s = lcast_get_precision(static_cast<Source*>(0)); +    std::streamsize const t = lcast_get_precision(static_cast<Target*>(0));      stream.precision(s > t ? s : t);  } diff --git a/3rdParty/Boost/src/boost/detail/scoped_enum_emulation.hpp b/3rdParty/Boost/src/boost/detail/scoped_enum_emulation.hpp index 644c138..e695a20 100644 --- a/3rdParty/Boost/src/boost/detail/scoped_enum_emulation.hpp +++ b/3rdParty/Boost/src/boost/detail/scoped_enum_emulation.hpp @@ -41,9 +41,9 @@  #ifdef BOOST_NO_SCOPED_ENUMS -# define BOOST_SCOPED_ENUM_START(name) struct name { enum enum_t +# define BOOST_SCOPED_ENUM_START(name) struct name { enum enum_type  # define BOOST_SCOPED_ENUM_END }; -# define BOOST_SCOPED_ENUM(name) name::enum_t +# define BOOST_SCOPED_ENUM(name) name::enum_type  #else diff --git a/3rdParty/Boost/src/boost/exception/detail/error_info_impl.hpp b/3rdParty/Boost/src/boost/exception/detail/error_info_impl.hpp index 32113b1..883d313 100644 --- a/3rdParty/Boost/src/boost/exception/detail/error_info_impl.hpp +++ b/3rdParty/Boost/src/boost/exception/detail/error_info_impl.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.  //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) @@ -25,7 +25,7 @@ boost              {              public: -            virtual char const * tag_typeid_name() const = 0; +            virtual std::string tag_typeid_name() const = 0;              virtual std::string value_as_string() const = 0;              protected: @@ -62,7 +62,7 @@ boost          private: -        char const * tag_typeid_name() const; +        std::string tag_typeid_name() const;          std::string value_as_string() const;          value_type value_; diff --git a/3rdParty/Boost/src/boost/exception/detail/exception_ptr.hpp b/3rdParty/Boost/src/boost/exception/detail/exception_ptr.hpp index 78db17c..59686e9 100644 --- a/3rdParty/Boost/src/boost/exception/detail/exception_ptr.hpp +++ b/3rdParty/Boost/src/boost/exception/detail/exception_ptr.hpp @@ -28,6 +28,26 @@  namespace  boost      { +    typedef shared_ptr<exception_detail::clone_base const> exception_ptr; + +    exception_ptr current_exception(); + +    template <class T> +    inline +    exception_ptr +    copy_exception( T const & e ) +        { +        try +            { +            throw enable_current_exception(e); +            } +        catch( +        ... ) +            { +            return current_exception(); +            } +        } +  #ifndef BOOST_NO_RTTI      typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type; @@ -39,91 +59,45 @@ boost          }  #endif -    class exception_ptr; -    exception_ptr current_exception(); -    void rethrow_exception( exception_ptr const & ); - -    class -    exception_ptr +    namespace +    exception_detail          { -        typedef bool exception_ptr::*unspecified_bool_type; -        friend exception_ptr current_exception(); -        friend void rethrow_exception( exception_ptr const & ); - -        shared_ptr<exception_detail::clone_base const> c_; -        bool bad_alloc_; -          struct -        bad_alloc_tag -            { -            }; - -        explicit -        exception_ptr( bad_alloc_tag ): -            bad_alloc_(true) -            { -            } - -        explicit -        exception_ptr( shared_ptr<exception_detail::clone_base const> const & c ): -            c_(c), -            bad_alloc_(false) -            { -            BOOST_ASSERT(c); -            } - -        void -        rethrow() const -            { -            BOOST_ASSERT(*this); -            if( bad_alloc_ ) -                throw enable_current_exception(std::bad_alloc()); -            else -                c_->rethrow(); -            } - -        bool -        empty() const -            { -            return !bad_alloc_ && !c_; -            } - -        public: - -        exception_ptr(): -            bad_alloc_(false) -            { -            } - -        ~exception_ptr() throw() -            { -            } +        bad_alloc_: +            boost::exception, +            std::bad_alloc +                { +                }; -        operator unspecified_bool_type() const +        template <int Dummy> +        exception_ptr +        get_bad_alloc()              { -            return empty() ? 0 : &exception_ptr::bad_alloc_; +            static exception_ptr e = boost::copy_exception( +                bad_alloc_() << +                throw_function("boost::current_exception()") << +                throw_file(__FILE__) << +                throw_line(__LINE__) ); +            return e;              } -        friend -        bool -        operator==( exception_ptr const & a, exception_ptr const & b ) +        template <int Dummy> +        struct +        exception_ptr_bad_alloc              { -            return a.c_==b.c_ && a.bad_alloc_==b.bad_alloc_; -            } +            static exception_ptr const e; +            }; -        friend -        bool -        operator!=( exception_ptr const & a, exception_ptr const & b ) -            { -            return !(a==b); -            } -        }; +        template <int Dummy> +        exception_ptr const +        exception_ptr_bad_alloc<Dummy>:: +        e = get_bad_alloc<Dummy>(); +        }      class      unknown_exception: -        public exception, -        public std::exception, -        public exception_detail::clone_base +        public boost::exception, +        public std::exception          {          public: @@ -150,18 +124,6 @@ boost          private: -        exception_detail::clone_base const * -        clone() const -            { -            return new unknown_exception(*this); -            } - -        void -        rethrow() const -            { -            throw*this; -            } -          template <class E>          void          add_original_type( E const & e ) @@ -179,8 +141,7 @@ boost          class          current_exception_std_exception_wrapper:              public T, -            public boost::exception, -            public clone_base +            public boost::exception              {              public: @@ -204,18 +165,6 @@ boost              private: -            clone_base const * -            clone() const -                { -                return new current_exception_std_exception_wrapper(*this); -                } - -            void -            rethrow() const -                { -                throw *this; -                } -              template <class E>              void              add_original_type( E const & e ) @@ -228,7 +177,7 @@ boost  #ifdef BOOST_NO_RTTI          template <class T> -        exception const * +        boost::exception const *          get_boost_exception( T const * )              {              try @@ -236,7 +185,7 @@ boost                  throw;                  }              catch( -            exception & x ) +            boost::exception & x )                  {                  return &x;                  } @@ -247,50 +196,50 @@ boost              }  #else          template <class T> -        exception const * +        boost::exception const *          get_boost_exception( T const * x )              { -            return dynamic_cast<exception const *>(x); +            return dynamic_cast<boost::exception const *>(x);              }  #endif          template <class T>          inline -        shared_ptr<clone_base const> +        exception_ptr          current_exception_std_exception( T const & e1 )              {              if( boost::exception const * e2 = get_boost_exception(&e1) ) -                return shared_ptr<current_exception_std_exception_wrapper<T> const>(new current_exception_std_exception_wrapper<T>(e1,*e2)); +                return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1,*e2));              else -                return shared_ptr<current_exception_std_exception_wrapper<T> const>(new current_exception_std_exception_wrapper<T>(e1)); +                return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1));              }          inline -        shared_ptr<clone_base const> +        exception_ptr          current_exception_unknown_exception()              { -            return shared_ptr<unknown_exception const>(new unknown_exception()); +            return boost::copy_exception(unknown_exception());              }          inline -        shared_ptr<clone_base const> +        exception_ptr          current_exception_unknown_boost_exception( boost::exception const & e )              { -            return shared_ptr<unknown_exception const>(new unknown_exception(e)); +            return boost::copy_exception(unknown_exception(e));              }          inline -        shared_ptr<clone_base const> +        exception_ptr          current_exception_unknown_std_exception( std::exception const & e )              {              if( boost::exception const * be = get_boost_exception(&e) )                  return current_exception_unknown_boost_exception(*be);              else -                return shared_ptr<unknown_exception const>(new unknown_exception(e)); +                return boost::copy_exception(unknown_exception(e));              }          inline -        shared_ptr<clone_base const> +        exception_ptr          current_exception_impl()              {              try @@ -300,7 +249,7 @@ boost              catch(              exception_detail::clone_base & e )                  { -                return shared_ptr<exception_detail::clone_base const>(e.clone()); +                return exception_ptr(e.clone());                  }              catch(              std::domain_error & e ) @@ -396,24 +345,28 @@ boost      exception_ptr      current_exception()          { +        exception_ptr ret; +        BOOST_ASSERT(!ret);          try              { -            return exception_ptr(exception_detail::current_exception_impl()); +            ret=exception_detail::current_exception_impl();              }          catch(          std::bad_alloc & )              { +            ret=exception_detail::exception_ptr_bad_alloc<42>::e;              }          catch(          ... )              {              try                  { -                return exception_ptr(exception_detail::current_exception_std_exception(std::bad_exception())); +                ret=exception_detail::current_exception_std_exception(std::bad_exception());                  }              catch(              std::bad_alloc & )                  { +                ret=exception_detail::exception_ptr_bad_alloc<42>::e;                  }              catch(              ... ) @@ -421,30 +374,16 @@ boost                  BOOST_ASSERT(0);                  }              } -        return exception_ptr(exception_ptr::bad_alloc_tag()); -        } - -    template <class T> -    inline -    exception_ptr -    copy_exception( T const & e ) -        { -        try -            { -            throw enable_current_exception(e); -            } -        catch( -        ... ) -            { -            return current_exception(); -            } +        BOOST_ASSERT(ret); +        return ret;          }      inline      void      rethrow_exception( exception_ptr const & p )          { -        p.rethrow(); +        BOOST_ASSERT(p); +        p->rethrow();          }      inline diff --git a/3rdParty/Boost/src/boost/exception/detail/is_output_streamable.hpp b/3rdParty/Boost/src/boost/exception/detail/is_output_streamable.hpp index 5eb1695..743313c 100644 --- a/3rdParty/Boost/src/boost/exception/detail/is_output_streamable.hpp +++ b/3rdParty/Boost/src/boost/exception/detail/is_output_streamable.hpp @@ -20,8 +20,21 @@ boost      namespace      to_string_detail          { -        template <class T,class CharT,class Traits> -        char operator<<( std::basic_ostream<CharT,Traits> &, T const & ); +        struct +        partial_ordering_helper1 +            { +            template <class CharT,class Traits> +            partial_ordering_helper1( std::basic_ostream<CharT,Traits> & ); +            }; + +        struct +        partial_ordering_helper2 +            { +            template <class T> +            partial_ordering_helper2( T const & ); +            }; + +        char operator<<( partial_ordering_helper1, partial_ordering_helper2 );          template <class T,class CharT,class Traits>          struct diff --git a/3rdParty/Boost/src/boost/exception/detail/type_info.hpp b/3rdParty/Boost/src/boost/exception/detail/type_info.hpp index 60709a1..9ab1c57 100644 --- a/3rdParty/Boost/src/boost/exception/detail/type_info.hpp +++ b/3rdParty/Boost/src/boost/exception/detail/type_info.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.  //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) @@ -15,31 +15,35 @@  #include <boost/detail/sp_typeinfo.hpp>  #include <boost/current_function.hpp>  #include <boost/config.hpp> +#ifndef BOOST_NO_TYPEID +#include <boost/units/detail/utility.hpp> +#endif +#include <string>  namespace  boost      {      template <class T>      inline -    char const * +    std::string      tag_type_name()          {  #ifdef BOOST_NO_TYPEID          return BOOST_CURRENT_FUNCTION;  #else -        return typeid(T*).name(); +        return units::detail::demangle(typeid(T*).name());  #endif          }      template <class T>      inline -    char const * +    std::string      type_name()          {  #ifdef BOOST_NO_TYPEID          return BOOST_CURRENT_FUNCTION;  #else -        return typeid(T).name(); +        return units::detail::demangle(typeid(T).name());  #endif          } diff --git a/3rdParty/Boost/src/boost/exception/diagnostic_information.hpp b/3rdParty/Boost/src/boost/exception/diagnostic_information.hpp index 632a5a3..1d6bc2c 100644 --- a/3rdParty/Boost/src/boost/exception/diagnostic_information.hpp +++ b/3rdParty/Boost/src/boost/exception/diagnostic_information.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.  //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) @@ -15,7 +15,9 @@  #include <boost/config.hpp>  #include <boost/exception/get_error_info.hpp>  #include <boost/utility/enable_if.hpp> -#include <boost/config.hpp> +#ifndef BOOST_NO_RTTI +#include <boost/units/detail/utility.hpp> +#endif  #include <exception>  #include <sstream>  #include <string> @@ -135,7 +137,7 @@ boost                  }  #ifndef BOOST_NO_RTTI              tmp << std::string("Dynamic exception type: ") << -                (be?BOOST_EXCEPTION_DYNAMIC_TYPEID(*be):BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)).type_.name() << '\n'; +                units::detail::demangle((be?BOOST_EXCEPTION_DYNAMIC_TYPEID(*be):BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)).type_.name()) << '\n';  #endif              if( with_what && se )                  tmp << "std::exception::what: " << wh << '\n'; diff --git a/3rdParty/Boost/src/boost/exception/exception.hpp b/3rdParty/Boost/src/boost/exception/exception.hpp index 79b2739..fd516dd 100644 --- a/3rdParty/Boost/src/boost/exception/exception.hpp +++ b/3rdParty/Boost/src/boost/exception/exception.hpp @@ -132,18 +132,6 @@ boost              }          }; -    template <class E,class Tag,class T> -    E const & operator<<( E const &, error_info<Tag,T> const & ); - -    template <class E> -    E const & operator<<( E const &, throw_function const & ); - -    template <class E> -    E const & operator<<( E const &, throw_file const & ); - -    template <class E> -    E const & operator<<( E const &, throw_line const & ); -      class exception;      template <class> @@ -163,6 +151,7 @@ boost              virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0;              virtual void add_ref() const = 0;              virtual void release() const = 0; +            virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0;              protected: @@ -184,6 +173,20 @@ boost          struct get_info<throw_line>;          char const * get_diagnostic_information( exception const &, char const * ); + +        void copy_boost_exception( exception *, exception const * ); + +        template <class E,class Tag,class T> +        E const & set_info( E const &, error_info<Tag,T> const & ); + +        template <class E> +        E const & set_info( E const &, throw_function const & ); + +        template <class E> +        E const & set_info( E const &, throw_file const & ); + +        template <class E> +        E const & set_info( E const &, throw_line const & );          }      class @@ -216,30 +219,31 @@ boost  #endif              ; -#if defined(__MWERKS__) && __MWERKS__<=0x3207 +#if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310)          public:  #else          private:          template <class E> -        friend E const & operator<<( E const &, throw_function const & ); +        friend E const & exception_detail::set_info( E const &, throw_function const & );          template <class E> -        friend E const & operator<<( E const &, throw_file const & ); +        friend E const & exception_detail::set_info( E const &, throw_file const & );          template <class E> -        friend E const & operator<<( E const &, throw_line const & ); - -        friend char const * exception_detail::get_diagnostic_information( exception const &, char const * ); +        friend E const & exception_detail::set_info( E const &, throw_line const & );          template <class E,class Tag,class T> -        friend E const & operator<<( E const &, error_info<Tag,T> const & ); +        friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & ); + +        friend char const * exception_detail::get_diagnostic_information( exception const &, char const * );          template <class>          friend struct exception_detail::get_info;          friend struct exception_detail::get_info<throw_function>;          friend struct exception_detail::get_info<throw_file>;          friend struct exception_detail::get_info<throw_line>; +        friend void exception_detail::copy_boost_exception( exception *, exception const * );  #endif          mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;          mutable char const * throw_function_; @@ -253,28 +257,32 @@ boost          {          } -    template <class E> -    E const & -    operator<<( E const & x, throw_function const & y ) +    namespace +    exception_detail          { -        x.throw_function_=y.v_; -        return x; -        } +        template <class E> +        E const & +        set_info( E const & x, throw_function const & y ) +            { +            x.throw_function_=y.v_; +            return x; +            } -    template <class E> -    E const & -    operator<<( E const & x, throw_file const & y ) -        { -        x.throw_file_=y.v_; -        return x; -        } +        template <class E> +        E const & +        set_info( E const & x, throw_file const & y ) +            { +            x.throw_file_=y.v_; +            return x; +            } -    template <class E> -    E const & -    operator<<( E const & x, throw_line const & y ) -        { -        x.throw_line_=y.v_; -        return x; +        template <class E> +        E const & +        set_info( E const & x, throw_line const & y ) +            { +            x.throw_line_=y.v_; +            return x; +            }          }      //////////////////////////////////////////////////////////////////////// @@ -300,10 +308,10 @@ boost              };          struct large_size { char c[256]; }; -        large_size dispatch( exception * ); +        large_size dispatch_boost_exception( exception const * );          struct small_size { }; -        small_size dispatch( void * ); +        small_size dispatch_boost_exception( void const * );          template <class,int>          struct enable_error_info_helper; @@ -326,7 +334,7 @@ boost          struct          enable_error_info_return_type              { -            typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch((T*)0))>::type type; +            typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception((T*)0))>::type type;              };          } @@ -363,7 +371,13 @@ boost          void          copy_boost_exception( exception * a, exception const * b )              { -            *a = *b; +            refcount_ptr<error_info_container> data; +            if( error_info_container * d=b->data_.get() ) +                data = d->clone(); +            a->throw_file_ = b->throw_file_; +            a->throw_line_ = b->throw_line_; +            a->throw_function_ = b->throw_function_; +            a->data_ = data;              }          inline diff --git a/3rdParty/Boost/src/boost/exception/info.hpp b/3rdParty/Boost/src/boost/exception/info.hpp index cbbc2c0..7aeeee5 100644 --- a/3rdParty/Boost/src/boost/exception/info.hpp +++ b/3rdParty/Boost/src/boost/exception/info.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.  //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) @@ -47,7 +47,7 @@ boost      template <class Tag,class T>      inline -    char const * +    std::string      error_info<Tag,T>::      tag_typeid_name() const          { @@ -131,6 +131,9 @@ boost              mutable std::string diagnostic_info_str_;              mutable int count_; +            error_info_container_impl( error_info_container_impl const & ); +            error_info_container_impl & operator=( error_info_container const & ); +              void              add_ref() const                  { @@ -143,21 +146,46 @@ boost                  if( !--count_ )                      delete this;                  } + +            refcount_ptr<error_info_container> +            clone() const +                { +                refcount_ptr<error_info_container> p; +                error_info_container_impl * c=new error_info_container_impl; +                p.adopt(c); +                c->info_ = info_; +                return p; +                } +            }; + +        template <class E,class Tag,class T> +        inline +        E const & +        set_info( E const & x, error_info<Tag,T> const & v ) +            { +            typedef error_info<Tag,T> error_info_tag_t; +            shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) ); +            exception_detail::error_info_container * c=x.data_.get(); +            if( !c ) +                x.data_.adopt(c=new exception_detail::error_info_container_impl); +            c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); +            return x; +            } + +        template <class T> +        struct +        derives_boost_exception +            { +            enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) };              };          }      template <class E,class Tag,class T>      inline -    E const & +    typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type      operator<<( E const & x, error_info<Tag,T> const & v )          { -        typedef error_info<Tag,T> error_info_tag_t; -        shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) ); -        exception_detail::error_info_container * c=x.data_.get(); -        if( !c ) -            x.data_.adopt(c=new exception_detail::error_info_container_impl); -        c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); -        return x; +        return exception_detail::set_info(x,v);          }      } diff --git a/3rdParty/Boost/src/boost/functional/hash/detail/hash_float_generic.hpp b/3rdParty/Boost/src/boost/functional/hash/detail/hash_float_generic.hpp index f9acee9..fdbf53f 100644 --- a/3rdParty/Boost/src/boost/functional/hash/detail/hash_float_generic.hpp +++ b/3rdParty/Boost/src/boost/functional/hash/detail/hash_float_generic.hpp @@ -51,17 +51,15 @@ namespace boost                      limits<T>::min_exponent;              } -            // The result of frexp is always between 0.5 and 1, so its -            // top bit will always be 1. Subtract by 0.5 to remove that. -            v -= T(0.5); -            v = ldexp(v, limits<std::size_t>::digits + 1); +            v = ldexp(v, limits<std::size_t>::digits);              std::size_t seed = static_cast<std::size_t>(v);              v -= seed;              // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1;              std::size_t const length                  = (limits<T>::digits * -                        boost::static_log2<limits<T>::radix>::value - 1) +                        boost::static_log2<limits<T>::radix>::value +                        + limits<std::size_t>::digits - 1)                  / limits<std::size_t>::digits;              for(std::size_t i = 0; i != length; ++i) diff --git a/3rdParty/Boost/src/boost/functional/hash/hash.hpp b/3rdParty/Boost/src/boost/functional/hash/hash.hpp index 1f33b9e..e85ca5a 100644 --- a/3rdParty/Boost/src/boost/functional/hash/hash.hpp +++ b/3rdParty/Boost/src/boost/functional/hash/hash.hpp @@ -44,7 +44,7 @@ namespace boost      std::size_t hash_value(wchar_t);  #endif -#if defined(BOOST_HAS_LONG_LONG) +#if !defined(BOOST_NO_LONG_LONG)      std::size_t hash_value(boost::long_long_type);      std::size_t hash_value(boost::ulong_long_type);  #endif @@ -174,7 +174,7 @@ namespace boost      }  #endif -#if defined(BOOST_HAS_LONG_LONG) +#if !defined(BOOST_NO_LONG_LONG)      inline std::size_t hash_value(boost::long_long_type v)      {          return hash_detail::hash_value_signed(v); @@ -408,7 +408,7 @@ namespace boost      BOOST_HASH_SPECIALIZE_REF(std::wstring)  #endif -#if defined(BOOST_HAS_LONG_LONG) +#if !defined(BOOST_NO_LONG_LONG)      BOOST_HASH_SPECIALIZE(boost::long_long_type)      BOOST_HASH_SPECIALIZE(boost::ulong_long_type)  #endif diff --git a/3rdParty/Boost/src/boost/iterator/iterator_concepts.hpp b/3rdParty/Boost/src/boost/iterator/iterator_concepts.hpp new file mode 100644 index 0000000..ced1112 --- /dev/null +++ b/3rdParty/Boost/src/boost/iterator/iterator_concepts.hpp @@ -0,0 +1,284 @@ +// (C) Copyright Jeremy Siek 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ITERATOR_CONCEPTS_HPP +#define BOOST_ITERATOR_CONCEPTS_HPP + +#include <boost/concept_check.hpp> +#include <boost/iterator/iterator_categories.hpp> + +// Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems. +#include <boost/detail/iterator.hpp> + +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_integral.hpp> + +#include <boost/mpl/bool.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/and.hpp> +#include <boost/mpl/or.hpp> + +#include <boost/static_assert.hpp> + +// Use boost/limits to work around missing limits headers on some compilers +#include <boost/limits.hpp> +#include <boost/config.hpp> + +#include <algorithm> + +#include <boost/concept/detail/concept_def.hpp> + +namespace boost_concepts +{ +  // Used a different namespace here (instead of "boost") so that the +  // concept descriptions do not take for granted the names in +  // namespace boost. + +  //=========================================================================== +  // Iterator Access Concepts + +  BOOST_concept(ReadableIterator,(Iterator)) +    : boost::Assignable<Iterator> +    , boost::CopyConstructible<Iterator> + +  { +      typedef BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<Iterator>::value_type value_type; +      typedef BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<Iterator>::reference reference; + +      BOOST_CONCEPT_USAGE(ReadableIterator) +      { + +          value_type v = *i; +          boost::ignore_unused_variable_warning(v); +      } +  private: +      Iterator i; +  }; +   +  template < +      typename Iterator +    , typename ValueType = BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<Iterator>::value_type +  > +  struct WritableIterator +    : boost::CopyConstructible<Iterator> +  { +      BOOST_CONCEPT_USAGE(WritableIterator) +      { +          *i = v; +      } +  private: +      ValueType v; +      Iterator i; +  }; + +  template < +      typename Iterator +    , typename ValueType = BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<Iterator>::value_type +  > +  struct WritableIteratorConcept : WritableIterator<Iterator,ValueType> {}; +   +  BOOST_concept(SwappableIterator,(Iterator)) +  { +      BOOST_CONCEPT_USAGE(SwappableIterator) +      { +          std::iter_swap(i1, i2); +      } +  private: +      Iterator i1; +      Iterator i2; +  }; + +  BOOST_concept(LvalueIterator,(Iterator)) +  { +      typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type; +       +      BOOST_CONCEPT_USAGE(LvalueIterator) +      { +        value_type& r = const_cast<value_type&>(*i); +        boost::ignore_unused_variable_warning(r); +      } +  private: +      Iterator i; +  }; + +   +  //=========================================================================== +  // Iterator Traversal Concepts + +  BOOST_concept(IncrementableIterator,(Iterator)) +    : boost::Assignable<Iterator> +    , boost::CopyConstructible<Iterator> +  { +      typedef typename boost::iterator_traversal<Iterator>::type traversal_category; + +      BOOST_CONCEPT_ASSERT(( +        boost::Convertible< +            traversal_category +          , boost::incrementable_traversal_tag +        >)); + +      BOOST_CONCEPT_USAGE(IncrementableIterator) +      { +          ++i; +          (void)i++; +      } +  private: +      Iterator i; +  }; + +  BOOST_concept(SinglePassIterator,(Iterator)) +    : IncrementableIterator<Iterator> +    , boost::EqualityComparable<Iterator> + +  { +      BOOST_CONCEPT_ASSERT(( +          boost::Convertible< +             BOOST_DEDUCED_TYPENAME SinglePassIterator::traversal_category +           , boost::single_pass_traversal_tag +          > )); +  }; + +  BOOST_concept(ForwardTraversal,(Iterator)) +    : SinglePassIterator<Iterator> +    , boost::DefaultConstructible<Iterator> +  { +      typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type; +       +      BOOST_MPL_ASSERT((boost::is_integral<difference_type>)); +      BOOST_MPL_ASSERT_RELATION(std::numeric_limits<difference_type>::is_signed, ==, true); + +      BOOST_CONCEPT_ASSERT(( +          boost::Convertible< +             BOOST_DEDUCED_TYPENAME ForwardTraversal::traversal_category +           , boost::forward_traversal_tag +          > )); +  }; +   +  BOOST_concept(BidirectionalTraversal,(Iterator)) +    : ForwardTraversal<Iterator> +  { +      BOOST_CONCEPT_ASSERT(( +          boost::Convertible< +             BOOST_DEDUCED_TYPENAME BidirectionalTraversal::traversal_category +           , boost::bidirectional_traversal_tag +          > )); + +      BOOST_CONCEPT_USAGE(BidirectionalTraversal) +      { +          --i; +          (void)i--; +      } +   private: +      Iterator i; +  }; + +  BOOST_concept(RandomAccessTraversal,(Iterator)) +    : BidirectionalTraversal<Iterator> +  { +      BOOST_CONCEPT_ASSERT(( +          boost::Convertible< +             BOOST_DEDUCED_TYPENAME RandomAccessTraversal::traversal_category +           , boost::random_access_traversal_tag +          > )); + +      BOOST_CONCEPT_USAGE(RandomAccessTraversal) +      { +          i += n; +          i = i + n; +          i = n + i; +          i -= n; +          i = i - n; +          n = i - j; +      } +       +   private: +      typename BidirectionalTraversal<Iterator>::difference_type n; +      Iterator i, j; +  }; + +  //=========================================================================== +  // Iterator Interoperability  + +  namespace detail +  { +    template <typename Iterator1, typename Iterator2> +    void interop_single_pass_constraints(Iterator1 const& i1, Iterator2 const& i2) +    { +        bool b; +        b = i1 == i2; +        b = i1 != i2; + +        b = i2 == i1; +        b = i2 != i1; +        boost::ignore_unused_variable_warning(b); +    } + +    template <typename Iterator1, typename Iterator2> +    void interop_rand_access_constraints( +        Iterator1 const& i1, Iterator2 const& i2, +        boost::random_access_traversal_tag, boost::random_access_traversal_tag) +    { +        bool b; +        typename boost::detail::iterator_traits<Iterator2>::difference_type n; +        b = i1 <  i2; +        b = i1 <= i2; +        b = i1 >  i2; +        b = i1 >= i2; +        n = i1 -  i2; + +        b = i2 <  i1; +        b = i2 <= i1; +        b = i2 >  i1; +        b = i2 >= i1; +        n = i2 -  i1; +        boost::ignore_unused_variable_warning(b); +        boost::ignore_unused_variable_warning(n); +    } + +    template <typename Iterator1, typename Iterator2> +    void interop_rand_access_constraints( +        Iterator1 const&, Iterator2 const&, +        boost::single_pass_traversal_tag, boost::single_pass_traversal_tag) +    { } + +  } // namespace detail + +  BOOST_concept(InteroperableIterator,(Iterator)(ConstIterator)) +  { +   private: +      typedef typename boost::detail::pure_traversal_tag< +          typename boost::iterator_traversal< +              Iterator +          >::type +      >::type traversal_category; + +      typedef typename boost::detail::pure_traversal_tag< +          typename boost::iterator_traversal< +              ConstIterator +          >::type +      >::type const_traversal_category; +       +  public: +      BOOST_CONCEPT_ASSERT((SinglePassIterator<Iterator>)); +      BOOST_CONCEPT_ASSERT((SinglePassIterator<ConstIterator>)); + +      BOOST_CONCEPT_USAGE(InteroperableIterator) +      { +          detail::interop_single_pass_constraints(i, ci); +          detail::interop_rand_access_constraints(i, ci, traversal_category(), const_traversal_category()); + +          ci = i; +      } +       +   private: +      Iterator      i; +      ConstIterator ci; +  }; + +} // namespace boost_concepts + +#include <boost/concept/detail/concept_undef.hpp> + +#endif // BOOST_ITERATOR_CONCEPTS_HPP diff --git a/3rdParty/Boost/src/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp b/3rdParty/Boost/src/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp index 3e7bfba..daec4b8 100644 --- a/3rdParty/Boost/src/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp +++ b/3rdParty/Boost/src/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp @@ -6,11 +6,10 @@  // http://www.boost.org/LICENSE_1_0.txt)  // -// Preprocessed version of "boost/mpl/aux_/template_arity.hpp" header +// *Preprocessed* version of the main "template_arity.hpp" header  // -- DO NOT modify by hand!  namespace boost { namespace mpl { namespace aux { -  template< int N > struct arity_tag  {      typedef char (&type)[N + 1]; @@ -23,7 +22,6 @@ struct max_arity  {      BOOST_STATIC_CONSTANT(int, value =            ( C6 > 0 ? C6 : ( C5 > 0 ? C5 : ( C4 > 0 ? C4 : ( C3 > 0 ? C3 : ( C2 > 0 ? C2 : ( C1 > 0 ? C1 : -1 ) ) ) ) ) ) -          );  }; @@ -83,7 +81,7 @@ template< typename F, int N >  struct template_arity_impl  {      BOOST_STATIC_CONSTANT(int, value = -          sizeof(arity_helper(type_wrapper<F>(), arity_tag<N>())) - 1 +          sizeof(::boost::mpl::aux::arity_helper(type_wrapper<F>(), arity_tag<N>())) - 1          );  }; @@ -92,9 +90,7 @@ struct template_arity  {      BOOST_STATIC_CONSTANT(int, value  = (            max_arity< template_arity_impl< F,1 >::value, template_arity_impl< F,2 >::value, template_arity_impl< F,3 >::value, template_arity_impl< F,4 >::value, template_arity_impl< F,5 >::value, template_arity_impl< F,6 >::value >::value -          )); -      typedef mpl::int_<value> type;  }; diff --git a/3rdParty/Boost/src/boost/mpl/aux_/template_arity.hpp b/3rdParty/Boost/src/boost/mpl/aux_/template_arity.hpp index 47e4eeb..ed26ea2 100644 --- a/3rdParty/Boost/src/boost/mpl/aux_/template_arity.hpp +++ b/3rdParty/Boost/src/boost/mpl/aux_/template_arity.hpp @@ -14,9 +14,9 @@  //  // See http://www.boost.org/libs/mpl for documentation. -// $Id: template_arity.hpp 49267 2008-10-11 06:19:02Z agurtovoy $ -// $Date: 2008-10-11 02:19:02 -0400 (Sat, 11 Oct 2008) $ -// $Revision: 49267 $ +// $Id: template_arity.hpp 61584 2010-04-26 18:48:26Z agurtovoy $ +// $Date: 2010-04-26 14:48:26 -0400 (Mon, 26 Apr 2010) $ +// $Revision: 61584 $  #include <boost/mpl/aux_/config/ttp.hpp>  #include <boost/mpl/aux_/config/lambda.hpp> @@ -98,7 +98,7 @@ template< typename F, BOOST_MPL_AUX_NTTP_DECL(int, N) >  struct template_arity_impl  {      BOOST_STATIC_CONSTANT(int, value =  -          sizeof(arity_helper(type_wrapper<F>(),arity_tag<N>())) - 1 +          sizeof(::boost::mpl::aux::arity_helper(type_wrapper<F>(),arity_tag<N>())) - 1          );  }; diff --git a/3rdParty/Boost/src/boost/mpl/aux_/unwrap.hpp b/3rdParty/Boost/src/boost/mpl/aux_/unwrap.hpp deleted file mode 100644 index dd710a7..0000000 --- a/3rdParty/Boost/src/boost/mpl/aux_/unwrap.hpp +++ /dev/null @@ -1,47 +0,0 @@ - -#ifndef BOOST_MPL_AUX_UNWRAP_HPP_INCLUDED -#define BOOST_MPL_AUX_UNWRAP_HPP_INCLUDED - -// Copyright Peter Dimov and Multi Media Ltd 2001, 2002 -// Copyright David Abrahams 2001 -// -// 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) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id: unwrap.hpp 49267 2008-10-11 06:19:02Z agurtovoy $ -// $Date: 2008-10-11 02:19:02 -0400 (Sat, 11 Oct 2008) $ -// $Revision: 49267 $ - -#include <boost/ref.hpp> - -namespace boost { namespace mpl { namespace aux { - -template< typename F > -inline -F& unwrap(F& f, long) -{ -    return f; -} - -template< typename F > -inline -F& -unwrap(reference_wrapper<F>& f, int) -{ -    return f; -} - -template< typename F > -inline -F& -unwrap(reference_wrapper<F> const& f, int) -{ -    return f; -} - -}}} - -#endif // BOOST_MPL_AUX_UNWRAP_HPP_INCLUDED diff --git a/3rdParty/Boost/src/boost/mpl/for_each.hpp b/3rdParty/Boost/src/boost/mpl/for_each.hpp deleted file mode 100644 index 89abc85..0000000 --- a/3rdParty/Boost/src/boost/mpl/for_each.hpp +++ /dev/null @@ -1,116 +0,0 @@ - -#ifndef BOOST_MPL_FOR_EACH_HPP_INCLUDED -#define BOOST_MPL_FOR_EACH_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2008 -// -// 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) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id: for_each.hpp 55648 2009-08-18 05:16:53Z agurtovoy $ -// $Date: 2009-08-18 01:16:53 -0400 (Tue, 18 Aug 2009) $ -// $Revision: 55648 $ - -#include <boost/mpl/is_sequence.hpp> -#include <boost/mpl/begin_end.hpp> -#include <boost/mpl/apply.hpp> -#include <boost/mpl/bool.hpp> -#include <boost/mpl/next_prior.hpp> -#include <boost/mpl/deref.hpp> -#include <boost/mpl/identity.hpp> -#include <boost/mpl/assert.hpp> -#include <boost/mpl/aux_/unwrap.hpp> - -#include <boost/type_traits/is_same.hpp> -#include <boost/utility/value_init.hpp> - -namespace boost { namespace mpl { - -namespace aux { - -template< bool done = true > -struct for_each_impl -{ -    template< -          typename Iterator -        , typename LastIterator -        , typename TransformFunc -        , typename F -        > -    static void execute( -          Iterator* -        , LastIterator* -        , TransformFunc* -        , F -        ) -    { -    } -}; - -template<> -struct for_each_impl<false> -{ -    template< -          typename Iterator -        , typename LastIterator -        , typename TransformFunc -        , typename F -        > -    static void execute( -          Iterator* -        , LastIterator* -        , TransformFunc*  -        , F f -        ) -    { -        typedef typename deref<Iterator>::type item; -        typedef typename apply1<TransformFunc,item>::type arg; -     -        // dwa 2002/9/10 -- make sure not to invoke undefined behavior -        // when we pass arg. -        value_initialized<arg> x; -        aux::unwrap(f, 0)(boost::get(x)); -         -        typedef typename mpl::next<Iterator>::type iter; -        for_each_impl<boost::is_same<iter,LastIterator>::value> -            ::execute( static_cast<iter*>(0), static_cast<LastIterator*>(0), static_cast<TransformFunc*>(0), f); -    } -}; - -} // namespace aux - -// agurt, 17/mar/02: pointer default parameters are necessary to workaround  -// MSVC 6.5 function template signature's mangling bug -template< -      typename Sequence -    , typename TransformOp -    , typename F -    > -inline -void for_each(F f, Sequence* = 0, TransformOp* = 0) -{ -    BOOST_MPL_ASSERT(( is_sequence<Sequence> )); - -    typedef typename begin<Sequence>::type first; -    typedef typename end<Sequence>::type last; - -    aux::for_each_impl< boost::is_same<first,last>::value > -        ::execute(static_cast<first*>(0), static_cast<last*>(0), static_cast<TransformOp*>(0), f); -} - -template< -      typename Sequence -    , typename F -    > -inline -void for_each(F f, Sequence* = 0) -{ -    for_each<Sequence, identity<> >(f); -} - -}} - -#endif // BOOST_MPL_FOR_EACH_HPP_INCLUDED diff --git a/3rdParty/Boost/src/boost/mpl/is_sequence.hpp b/3rdParty/Boost/src/boost/mpl/is_sequence.hpp deleted file mode 100644 index 0c1f67b..0000000 --- a/3rdParty/Boost/src/boost/mpl/is_sequence.hpp +++ /dev/null @@ -1,112 +0,0 @@ - -#ifndef BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED -#define BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2002-2004 -// -// 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) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id: is_sequence.hpp 49267 2008-10-11 06:19:02Z agurtovoy $ -// $Date: 2008-10-11 02:19:02 -0400 (Sat, 11 Oct 2008) $ -// $Revision: 49267 $ - -#include <boost/mpl/not.hpp> -#include <boost/mpl/and.hpp> -#include <boost/mpl/begin_end.hpp> -#include <boost/mpl/if.hpp> -#include <boost/mpl/bool.hpp> -#include <boost/mpl/sequence_tag_fwd.hpp> -#include <boost/mpl/identity.hpp> -#include <boost/mpl/void.hpp> -#include <boost/mpl/aux_/has_tag.hpp> -#include <boost/mpl/aux_/has_begin.hpp> -#include <boost/mpl/aux_/na_spec.hpp> -#include <boost/mpl/aux_/lambda_support.hpp> -#include <boost/mpl/aux_/config/eti.hpp> -#include <boost/mpl/aux_/config/msvc.hpp> -#include <boost/mpl/aux_/config/workaround.hpp> -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -#   include <boost/mpl/aux_/msvc_is_class.hpp> -#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300) -#   include <boost/type_traits/is_class.hpp> -#endif - -#include <boost/type_traits/is_same.hpp> - -namespace boost { namespace mpl { - -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - -namespace aux { - -// agurt, 11/jun/03:  -// MSVC 6.5/7.0 fails if 'has_begin' is instantiated on a class type that has a -// 'begin' member that doesn't name a type; e.g. 'has_begin< std::vector<int> >' -// would fail; requiring 'T' to have _both_ 'tag' and 'begin' members workarounds -// the issue for most real-world cases -template< typename T > struct is_sequence_impl -    : and_< -          identity< aux::has_tag<T> > -        , identity< aux::has_begin<T> > -        > -{ -}; - -} // namespace aux -         -template< -      typename BOOST_MPL_AUX_NA_PARAM(T) -    > -struct is_sequence -    : if_< -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -          aux::msvc_is_class<T>  -#else -          boost::is_class<T>  -#endif -        , aux::is_sequence_impl<T> -        , bool_<false> -        >::type -{ -    BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T)) -}; - -#elif defined(BOOST_MPL_CFG_NO_HAS_XXX) - -template< -      typename BOOST_MPL_AUX_NA_PARAM(T) -    > -struct is_sequence -    : bool_<false> -{ -}; - -#else - -template< -      typename BOOST_MPL_AUX_NA_PARAM(T) -    > -struct is_sequence -    : not_< is_same< typename begin<T>::type, void_ > > -{ -    BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T)) -}; - -#endif // BOOST_MSVC - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) -template<> struct is_sequence<int> -    : bool_<false> -{ -}; -#endif - -BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, is_sequence) - -}} - -#endif // BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED diff --git a/3rdParty/Boost/src/boost/preprocessor/seq/for_each.hpp b/3rdParty/Boost/src/boost/preprocessor/seq/for_each.hpp deleted file mode 100644 index e997a9a..0000000 --- a/3rdParty/Boost/src/boost/preprocessor/seq/for_each.hpp +++ /dev/null @@ -1,60 +0,0 @@ -# /* ************************************************************************** -#  *                                                                          * -#  *     (C) Copyright Paul Mensonides 2002. -#  *     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) -#  *                                                                          * -#  ************************************************************************** */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_SEQ_FOR_EACH_HPP -# define BOOST_PREPROCESSOR_SEQ_FOR_EACH_HPP -# -# include <boost/preprocessor/arithmetic/dec.hpp> -# include <boost/preprocessor/config/config.hpp> -# include <boost/preprocessor/repetition/for.hpp> -# include <boost/preprocessor/seq/seq.hpp> -# include <boost/preprocessor/seq/size.hpp> -# include <boost/preprocessor/tuple/elem.hpp> -# include <boost/preprocessor/tuple/rem.hpp> -# -# /* BOOST_PP_SEQ_FOR_EACH */ -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -#    define BOOST_PP_SEQ_FOR_EACH(macro, data, seq) BOOST_PP_FOR((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) -# else -#    define BOOST_PP_SEQ_FOR_EACH(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_D(macro, data, seq) -#    define BOOST_PP_SEQ_FOR_EACH_D(macro, data, seq) BOOST_PP_FOR((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) -# endif -# -# define BOOST_PP_SEQ_FOR_EACH_P(r, x) BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(3, 2, x))) -# -# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -#    define BOOST_PP_SEQ_FOR_EACH_O(r, x) BOOST_PP_SEQ_FOR_EACH_O_I x -# else -#    define BOOST_PP_SEQ_FOR_EACH_O(r, x) BOOST_PP_SEQ_FOR_EACH_O_I(BOOST_PP_TUPLE_ELEM(3, 0, x), BOOST_PP_TUPLE_ELEM(3, 1, x), BOOST_PP_TUPLE_ELEM(3, 2, x)) -# endif -# -# define BOOST_PP_SEQ_FOR_EACH_O_I(macro, data, seq) (macro, data, BOOST_PP_SEQ_TAIL(seq)) -# -# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -#    define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_IM(r, BOOST_PP_TUPLE_REM_3 x) -#    define BOOST_PP_SEQ_FOR_EACH_M_IM(r, im) BOOST_PP_SEQ_FOR_EACH_M_I(r, im) -# else -#    define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_I(r, BOOST_PP_TUPLE_ELEM(3, 0, x), BOOST_PP_TUPLE_ELEM(3, 1, x), BOOST_PP_TUPLE_ELEM(3, 2, x)) -# endif -# -# define BOOST_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq) macro(r, data, BOOST_PP_SEQ_HEAD(seq)) -# -# /* BOOST_PP_SEQ_FOR_EACH_R */ -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -#    define BOOST_PP_SEQ_FOR_EACH_R(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) -# else -#    define BOOST_PP_SEQ_FOR_EACH_R(r, macro, data, seq) BOOST_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) -#    define BOOST_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) -# endif -# -# endif diff --git a/3rdParty/Boost/src/boost/progress.hpp b/3rdParty/Boost/src/boost/progress.hpp deleted file mode 100644 index fbbf04a..0000000 --- a/3rdParty/Boost/src/boost/progress.hpp +++ /dev/null @@ -1,143 +0,0 @@ -//  boost progress.hpp header file  ------------------------------------------// - -//  Copyright Beman Dawes 1994-99.  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) - -//  See http://www.boost.org/libs/timer for documentation. - -//  Revision History -//   1 Dec 01  Add leading progress display strings (suggested by Toon Knapen) -//  20 May 01  Introduce several static_casts<> to eliminate warning messages -//             (Fixed by Beman, reported by Herve Bronnimann) -//  12 Jan 01  Change to inline implementation to allow use without library -//             builds. See docs for more rationale. (Beman Dawes)  -//  22 Jul 99  Name changed to .hpp -//  16 Jul 99  Second beta -//   6 Jul 99  Initial boost version - -#ifndef BOOST_PROGRESS_HPP -#define BOOST_PROGRESS_HPP - -#include <boost/timer.hpp> -#include <boost/utility.hpp>  // for noncopyable -#include <boost/cstdint.hpp>  // for uintmax_t -#include <iostream>           // for ostream, cout, etc -#include <string>             // for string - -namespace boost { - -//  progress_timer  ----------------------------------------------------------// - -//  A progress_timer behaves like a timer except that the destructor displays -//  an elapsed time message at an appropriate place in an appropriate form. - -class progress_timer : public timer, private noncopyable -{ -   - public: -  explicit progress_timer( std::ostream & os = std::cout ) -     // os is hint; implementation may ignore, particularly in embedded systems -     : m_os(os) {} -  ~progress_timer() -  { -  //  A) Throwing an exception from a destructor is a Bad Thing. -  //  B) The progress_timer destructor does output which may throw. -  //  C) A progress_timer is usually not critical to the application. -  //  Therefore, wrap the I/O in a try block, catch and ignore all exceptions. -    try -    { -      // use istream instead of ios_base to workaround GNU problem (Greg Chicares) -      std::istream::fmtflags old_flags = m_os.setf( std::istream::fixed, -                                                   std::istream::floatfield ); -      std::streamsize old_prec = m_os.precision( 2 ); -      m_os << elapsed() << " s\n" // "s" is System International d'Unites std -                        << std::endl; -      m_os.flags( old_flags ); -      m_os.precision( old_prec ); -    } - -    catch (...) {} // eat any exceptions -  } // ~progress_timer - - private: -  std::ostream & m_os; -}; - - -//  progress_display  --------------------------------------------------------// - -//  progress_display displays an appropriate indication of  -//  progress at an appropriate place in an appropriate form. - -// NOTE: (Jan 12, 2001) Tried to change unsigned long to boost::uintmax_t, but -// found some compilers couldn't handle the required conversion to double. -// Reverted to unsigned long until the compilers catch up.  - -class progress_display : private noncopyable -{ - public: -  explicit progress_display( unsigned long expected_count, -                             std::ostream & os = std::cout, -                             const std::string & s1 = "\n", //leading strings -                             const std::string & s2 = "", -                             const std::string & s3 = "" ) -   // os is hint; implementation may ignore, particularly in embedded systems -   : m_os(os), m_s1(s1), m_s2(s2), m_s3(s3) { restart(expected_count); } - -  void           restart( unsigned long expected_count ) -  //  Effects: display appropriate scale -  //  Postconditions: count()==0, expected_count()==expected_count -  { -    _count = _next_tic_count = _tic = 0; -    _expected_count = expected_count; - -    m_os << m_s1 << "0%   10   20   30   40   50   60   70   80   90   100%\n" -         << m_s2 << "|----|----|----|----|----|----|----|----|----|----|" -         << std::endl  // endl implies flush, which ensures display -         << m_s3; -    if ( !_expected_count ) _expected_count = 1;  // prevent divide by zero -  } // restart - -  unsigned long  operator+=( unsigned long increment ) -  //  Effects: Display appropriate progress tic if needed. -  //  Postconditions: count()== original count() + increment -  //  Returns: count(). -  { -    if ( (_count += increment) >= _next_tic_count ) { display_tic(); } -    return _count; -  } - -  unsigned long  operator++()           { return operator+=( 1 ); } -  unsigned long  count() const          { return _count; } -  unsigned long  expected_count() const { return _expected_count; } - -  private: -  std::ostream &     m_os;  // may not be present in all imps -  const std::string  m_s1;  // string is more general, safer than  -  const std::string  m_s2;  //  const char *, and efficiency or size are -  const std::string  m_s3;  //  not issues - -  unsigned long _count, _expected_count, _next_tic_count; -  unsigned int  _tic; -  void display_tic() -  { -    // use of floating point ensures that both large and small counts -    // work correctly.  static_cast<>() is also used several places -    // to suppress spurious compiler warnings.  -    unsigned int tics_needed = -      static_cast<unsigned int>( -        (static_cast<double>(_count)/_expected_count)*50.0 ); -    do { m_os << '*' << std::flush; } while ( ++_tic < tics_needed ); -    _next_tic_count =  -      static_cast<unsigned long>((_tic/50.0)*_expected_count); -    if ( _count == _expected_count ) { -      if ( _tic < 51 ) m_os << '*'; -      m_os << std::endl; -      } -  } // display_tic -}; - -} // namespace boost - -#endif  // BOOST_PROGRESS_HPP diff --git a/3rdParty/Boost/src/boost/range/algorithm/equal.hpp b/3rdParty/Boost/src/boost/range/algorithm/equal.hpp new file mode 100755 index 0000000..7226440 --- /dev/null +++ b/3rdParty/Boost/src/boost/range/algorithm/equal.hpp @@ -0,0 +1,188 @@ +// Boost.Range library +// +//  Copyright Neil Groves 2009. +//  Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EQUAL_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EQUAL_HPP_INCLUDED + +#include <boost/config.hpp> +#include <boost/range/concepts.hpp> +#include <iterator> + +namespace boost +{ +    namespace range_detail +    { +        // An implementation of equality comparison that is optimized for iterator +        // traversal categories less than RandomAccessTraversal. +        template< class SinglePassTraversalReadableIterator1, +                  class SinglePassTraversalReadableIterator2, +                  class IteratorCategoryTag1, +                  class IteratorCategoryTag2 > +        inline bool equal_impl( SinglePassTraversalReadableIterator1 first1, +                                SinglePassTraversalReadableIterator1 last1, +                                SinglePassTraversalReadableIterator2 first2, +                                SinglePassTraversalReadableIterator2 last2, +                                IteratorCategoryTag1, +                                IteratorCategoryTag2 ) +        { +            do +            { +                // If we have reached the end of the left range then this is +                // the end of the loop. They are equal if and only if we have +                // simultaneously reached the end of the right range. +                if (first1 == last1) +                    return first2 == last2; + +                // If we have reached the end of the right range at this line +                // it indicates that the right range is shorter than the left +                // and hence the result is false. +                if (first2 == last2) +                    return false; + +                // continue looping if and only if the values are equal +            } while(*first1++ == *first2++); + +            // Reaching this line in the algorithm indicates that a value +            // inequality has been detected. +            return false; +        } + +        template< class SinglePassTraversalReadableIterator1, +                  class SinglePassTraversalReadableIterator2, +                  class IteratorCategoryTag1, +                  class IteratorCategoryTag2, +                  class BinaryPredicate > +        inline bool equal_impl( SinglePassTraversalReadableIterator1 first1, +                                SinglePassTraversalReadableIterator1 last1, +                                SinglePassTraversalReadableIterator2 first2, +                                SinglePassTraversalReadableIterator2 last2, +                                BinaryPredicate                      pred, +                                IteratorCategoryTag1, +                                IteratorCategoryTag2 ) +        { +            do +            { +                // If we have reached the end of the left range then this is +                // the end of the loop. They are equal if and only if we have +                // simultaneously reached the end of the right range. +                if (first1 == last1) +                    return first2 == last2; + +                // If we have reached the end of the right range at this line +                // it indicates that the right range is shorter than the left +                // and hence the result is false. +                if (first2 == last2) +                    return false; + +                // continue looping if and only if the values are equal +            } while(pred(*first1++, *first2++)); + +            // Reaching this line in the algorithm indicates that a value +            // inequality has been detected. +            return false; +        } + +        // An implementation of equality comparison that is optimized for +        // random access iterators. +        template< class RandomAccessTraversalReadableIterator1, +                  class RandomAccessTraversalReadableIterator2 > +        inline bool equal_impl( RandomAccessTraversalReadableIterator1 first1, +                                RandomAccessTraversalReadableIterator1 last1, +                                RandomAccessTraversalReadableIterator2 first2, +                                RandomAccessTraversalReadableIterator2 last2, +                                std::random_access_iterator_tag, +                                std::random_access_iterator_tag ) +        { +            return ((last1 - first1) == (last2 - first2)) +                && std::equal(first1, last1, first2); +        } + +        template< class RandomAccessTraversalReadableIterator1, +                  class RandomAccessTraversalReadableIterator2, +                  class BinaryPredicate > +        inline bool equal_impl( RandomAccessTraversalReadableIterator1 first1, +                                RandomAccessTraversalReadableIterator1 last1, +                                RandomAccessTraversalReadableIterator2 first2, +                                RandomAccessTraversalReadableIterator2 last2, +                                BinaryPredicate                        pred ) +        { +            return ((last1 - first1) == (last2 - first2)) +                && std::equal(first1, last1, first2, pred); +        } + +        template< class SinglePassTraversalReadableIterator1, +                  class SinglePassTraversalReadableIterator2 > +        inline bool equal( SinglePassTraversalReadableIterator1 first1, +                           SinglePassTraversalReadableIterator1 last1, +                           SinglePassTraversalReadableIterator2 first2, +                           SinglePassTraversalReadableIterator2 last2 ) +        { +            BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator1 >::iterator_category tag1; +            BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator2 >::iterator_category tag2; + +            return equal_impl(first1, last1, first2, last2, tag1, tag2); +        } + +        template< class SinglePassTraversalReadableIterator1, +                  class SinglePassTraversalReadableIterator2, +                  class BinaryPredicate > +        inline bool equal( SinglePassTraversalReadableIterator1 first1, +                           SinglePassTraversalReadableIterator1 last1, +                           SinglePassTraversalReadableIterator2 first2, +                           SinglePassTraversalReadableIterator2 last2, +                           BinaryPredicate                      pred ) +        { +            BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator1 >::iterator_category tag1; +            BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator2 >::iterator_category tag2; + +            return equal_impl(first1, last1, first2, last2, pred, tag1, tag2); +        } + +    } // namespace range_detail + +    namespace range +    { + +        /// \brief template function equal +        /// +        /// range-based version of the equal std algorithm +        /// +        /// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +        /// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +        /// \pre BinaryPredicate is a model of the BinaryPredicateConcept +        template< class SinglePassRange1, class SinglePassRange2 > +        inline bool equal( const SinglePassRange1& rng1, const SinglePassRange2& rng2 ) +        { +            BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange1> )); +            BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange2> )); + +            return ::boost::range_detail::equal( +                ::boost::begin(rng1), ::boost::end(rng1), +                ::boost::begin(rng2), ::boost::end(rng2) ); +        } + +        /// \overload +        template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > +        inline bool equal( const SinglePassRange1& rng1, const SinglePassRange2& rng2, +                           BinaryPredicate pred ) +        { +            BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange1> )); +            BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange2> )); + +            return ::boost::range_detail::equal( +                ::boost::begin(rng1), ::boost::end(rng1), +                ::boost::begin(rng2), ::boost::end(rng2), +                pred); +        } + +    } // namespace range +    using range::equal; +} // namespace boost + +#endif // include guard diff --git a/3rdParty/Boost/src/boost/range/as_literal.hpp b/3rdParty/Boost/src/boost/range/as_literal.hpp index 2f04ca8..f67ead7 100644 --- a/3rdParty/Boost/src/boost/range/as_literal.hpp +++ b/3rdParty/Boost/src/boost/range/as_literal.hpp @@ -25,7 +25,7 @@  #include <boost/detail/workaround.hpp>  #include <cstring> -#ifndef BOOST_NO_CWCHAR  +#ifndef BOOST_NO_CWCHAR  #include <cwchar>  #endif @@ -38,41 +38,41 @@ namespace boost              return strlen( s );          } -#ifndef BOOST_NO_CWCHAR   +#ifndef BOOST_NO_CWCHAR          inline std::size_t length( const wchar_t* s )          {              return wcslen( s );          } -#endif         +#endif          //          // Remark: the compiler cannot choose between T* and T[sz]          // overloads, so we must put the T* internal to the          // unconstrained version. -        //  +        //          inline bool is_char_ptr( char* )          {              return true;          } -         +          inline bool is_char_ptr( const char* )          {              return true;          } -#ifndef BOOST_NO_CWCHAR   +#ifndef BOOST_NO_CWCHAR          inline bool is_char_ptr( wchar_t* )          {              return true;          } -         +          inline bool is_char_ptr( const wchar_t* )          {              return true;          }  #endif -         +          template< class T >          inline long is_char_ptr( T /* r */ )          { @@ -80,30 +80,30 @@ namespace boost          }          template< class T > -        inline iterator_range<T*>  +        inline iterator_range<T*>          make_range( T* const r, bool )          {              return iterator_range<T*>( r, r + length(r) );          }          template< class T > -        inline iterator_range<BOOST_DEDUCED_TYPENAME range_iterator<T>::type>  +        inline iterator_range<BOOST_DEDUCED_TYPENAME range_iterator<T>::type>          make_range( T& r, long )          {              return boost::make_iterator_range( r );          }      } -     +      template< class Range > -    inline iterator_range<BOOST_DEDUCED_TYPENAME range_iterator<Range>::type>  +    inline iterator_range<BOOST_DEDUCED_TYPENAME range_iterator<Range>::type>      as_literal( Range& r )      {          return range_detail::make_range( r, range_detail::is_char_ptr(r) );      }      template< class Range > -    inline iterator_range<BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type>  +    inline iterator_range<BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type>      as_literal( const Range& r )      {          return range_detail::make_range( r, range_detail::is_char_ptr(r) ); @@ -112,9 +112,9 @@ namespace boost      template< class Char, std::size_t sz >      inline iterator_range<Char*> as_literal( Char (&arr)[sz] )      { -        return range_detail::make_range( arr, range_detail::is_char_ptr(arr) );         +        return range_detail::make_range( arr, range_detail::is_char_ptr(arr) );      } -     +      template< class Char, std::size_t sz >      inline iterator_range<const Char*> as_literal( const Char (&arr)[sz] )      { diff --git a/3rdParty/Boost/src/boost/range/concepts.hpp b/3rdParty/Boost/src/boost/range/concepts.hpp new file mode 100644 index 0000000..8e4d2cf --- /dev/null +++ b/3rdParty/Boost/src/boost/range/concepts.hpp @@ -0,0 +1,331 @@ +// Boost.Range library concept checks +// +//  Copyright Neil Groves 2009. Use, modification and distribution +//  are subject to 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) +// +//  Copyright Daniel Walker 2006. Use, modification and distribution +//  are subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_CONCEPTS_HPP +#define BOOST_RANGE_CONCEPTS_HPP + +#include <boost/concept_check.hpp> +#include <boost/iterator/iterator_concepts.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/value_type.hpp> +#include <boost/range/detail/misc_concept.hpp> + +/*! + * \file + * \brief Concept checks for the Boost Range library. + * + * The structures in this file may be used in conjunction with the + * Boost Concept Check library to insure that the type of a function + * parameter is compatible with a range concept. If not, a meaningful + * compile time error is generated. Checks are provided for the range + * concepts related to iterator traversal categories. For example, the + * following line checks that the type T models the ForwardRange + * concept. + * + * \code + * BOOST_CONCEPT_ASSERT((ForwardRangeConcept<T>)); + * \endcode + * + * A different concept check is required to ensure writeable value + * access. For example to check for a ForwardRange that can be written + * to, the following code is required. + * + * \code + * BOOST_CONCEPT_ASSERT((WriteableForwardRangeConcept<T>)); + * \endcode + * + * \see http://www.boost.org/libs/range/doc/range.html for details + * about range concepts. + * \see http://www.boost.org/libs/iterator/doc/iterator_concepts.html + * for details about iterator concepts. + * \see http://www.boost.org/libs/concept_check/concept_check.htm for + * details about concept checks. + */ + +namespace boost { + +    namespace range_detail { + +#ifndef BOOST_RANGE_ENABLE_CONCEPT_ASSERT + +// List broken compiler versions here: +    #ifdef __GNUC__ +        // GNUC 4.2 has strange issues correctly detecting compliance with the Concepts +        // hence the least disruptive approach is to turn-off the concept checking for +        // this version of the compiler. +        #if __GNUC__ == 4 && __GNUC_MINOR__ == 2 +            #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 +        #endif +    #endif + +    #ifdef __BORLANDC__ +        #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 +    #endif + +    #ifdef __PATHCC__ +        #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 +    #endif + +// Default to using the concept asserts unless we have defined it off +// during the search for black listed compilers. +    #ifndef BOOST_RANGE_ENABLE_CONCEPT_ASSERT +        #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 1 +    #endif + +#endif + +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +    #define BOOST_RANGE_CONCEPT_ASSERT( x ) BOOST_CONCEPT_ASSERT( x ) +#else +    #define BOOST_RANGE_CONCEPT_ASSERT( x ) +#endif + +        // Rationale for the inclusion of redefined iterator concept +        // classes: +        // +        // The Range algorithms often do not require that the iterators are +        // Assignable, but the correct standard conformant iterators +        // do require the iterators to be a model of the Assignable concept. +        // Iterators that contains a functor that is not assignable therefore +        // are not correct models of the standard iterator concepts, +        // despite being adequate for most algorithms. An example of this +        // use case is the combination of the boost::adaptors::filtered +        // class with a boost::lambda::bind generated functor. +        // Ultimately modeling the range concepts using composition +        // with the Boost.Iterator concepts would render the library +        // incompatible with many common Boost.Lambda expressions. +        template<class Iterator> +        struct IncrementableIteratorConcept : CopyConstructible<Iterator> +        { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +            typedef BOOST_DEDUCED_TYPENAME iterator_traversal<Iterator>::type traversal_category; + +            BOOST_RANGE_CONCEPT_ASSERT(( +                Convertible< +                    traversal_category, +                    incrementable_traversal_tag +                >)); + +            BOOST_CONCEPT_USAGE(IncrementableIteratorConcept) +            { +                ++i; +                (void)i++; +            } +        private: +            Iterator i; +#endif +        }; + +        template<class Iterator> +        struct SinglePassIteratorConcept +            : IncrementableIteratorConcept<Iterator> +            , EqualityComparable<Iterator> +        { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +            BOOST_RANGE_CONCEPT_ASSERT(( +                Convertible< +                    BOOST_DEDUCED_TYPENAME SinglePassIteratorConcept::traversal_category, +                    single_pass_traversal_tag +                >)); +#endif +        }; + +        template<class Iterator> +        struct ForwardIteratorConcept +            : SinglePassIteratorConcept<Iterator> +            , DefaultConstructible<Iterator> +        { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +            typedef BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<Iterator>::difference_type difference_type; + +            BOOST_MPL_ASSERT((is_integral<difference_type>)); +            BOOST_MPL_ASSERT_RELATION(std::numeric_limits<difference_type>::is_signed, ==, true); + +            BOOST_RANGE_CONCEPT_ASSERT(( +                Convertible< +                    BOOST_DEDUCED_TYPENAME ForwardIteratorConcept::traversal_category, +                    forward_traversal_tag +                >)); +#endif +         }; + +         template<class Iterator> +         struct BidirectionalIteratorConcept +             : ForwardIteratorConcept<Iterator> +         { + #if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +             BOOST_RANGE_CONCEPT_ASSERT(( +                 Convertible< +                     BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::traversal_category, +                     bidirectional_traversal_tag +                 >)); + +             BOOST_CONCEPT_USAGE(BidirectionalIteratorConcept) +             { +                 --i; +                 (void)i--; +             } +         private: +             Iterator i; + #endif +         }; + +         template<class Iterator> +         struct RandomAccessIteratorConcept +             : BidirectionalIteratorConcept<Iterator> +         { + #if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +             BOOST_RANGE_CONCEPT_ASSERT(( +                 Convertible< +                     BOOST_DEDUCED_TYPENAME RandomAccessIteratorConcept::traversal_category, +                     random_access_traversal_tag +                 >)); + +             BOOST_CONCEPT_USAGE(RandomAccessIteratorConcept) +             { +                 i += n; +                 i = i + n; +                 i = n + i; +                 i -= n; +                 i = i - n; +                 n = i - j; +             } +         private: +             BOOST_DEDUCED_TYPENAME RandomAccessIteratorConcept::difference_type n; +             Iterator i; +             Iterator j; + #endif +         }; + +    } // namespace range_detail + +    //! Check if a type T models the SinglePassRange range concept. +    template<class T> +    struct SinglePassRangeConcept +    { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +         typedef BOOST_DEDUCED_TYPENAME range_iterator<T const>::type  const_iterator; +         typedef BOOST_DEDUCED_TYPENAME range_iterator<T>::type        iterator; + +         BOOST_RANGE_CONCEPT_ASSERT((range_detail::SinglePassIteratorConcept<iterator>)); +         BOOST_RANGE_CONCEPT_ASSERT((range_detail::SinglePassIteratorConcept<const_iterator>)); + +         BOOST_CONCEPT_USAGE(SinglePassRangeConcept) +         { +            // This has been modified from assigning to this->i +            // (where i was a member variable) to improve +            // compatibility with Boost.Lambda +            iterator i1 = boost::begin(*m_range); +            iterator i2 = boost::end(*m_range); + +            ignore_unused_variable_warning(i1); +            ignore_unused_variable_warning(i2); + +            const_constraints(*m_range); +        } + +    private: +        void const_constraints(const T& const_range) +        { +            const_iterator ci1 = boost::begin(const_range); +            const_iterator ci2 = boost::end(const_range); + +            ignore_unused_variable_warning(ci1); +            ignore_unused_variable_warning(ci2); +        } + +       // Rationale: +       // The type of m_range is T* rather than T because it allows +       // T to be an abstract class. The other obvious alternative of +       // T& produces a warning on some compilers. +       T* m_range; +#endif +    }; + +    //! Check if a type T models the ForwardRange range concept. +    template<class T> +    struct ForwardRangeConcept : SinglePassRangeConcept<T> +    { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +        BOOST_RANGE_CONCEPT_ASSERT((range_detail::ForwardIteratorConcept<BOOST_DEDUCED_TYPENAME ForwardRangeConcept::iterator>)); +        BOOST_RANGE_CONCEPT_ASSERT((range_detail::ForwardIteratorConcept<BOOST_DEDUCED_TYPENAME ForwardRangeConcept::const_iterator>)); +#endif +    }; + +    template<class Range> +    struct WriteableRangeConcept +    { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +        typedef BOOST_DEDUCED_TYPENAME range_iterator<Range>::type iterator; + +        BOOST_CONCEPT_USAGE(WriteableRangeConcept) +        { +            *i = v; +        } +    private: +        iterator i; +        BOOST_DEDUCED_TYPENAME range_value<Range>::type v; +#endif +    }; + +    //! Check if a type T models the WriteableForwardRange range concept. +    template<class T> +    struct WriteableForwardRangeConcept +        : ForwardRangeConcept<T> +        , WriteableRangeConcept<T> +    { +    }; + +    //! Check if a type T models the BidirectionalRange range concept. +    template<class T> +    struct BidirectionalRangeConcept : ForwardRangeConcept<T> +    { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +        BOOST_RANGE_CONCEPT_ASSERT((BidirectionalIteratorConcept<BOOST_DEDUCED_TYPENAME BidirectionalRangeConcept::iterator>)); +        BOOST_RANGE_CONCEPT_ASSERT((BidirectionalIteratorConcept<BOOST_DEDUCED_TYPENAME BidirectionalRangeConcept::const_iterator>)); +#endif +    }; + +    //! Check if a type T models the WriteableBidirectionalRange range concept. +    template<class T> +    struct WriteableBidirectionalRangeConcept +        : BidirectionalRangeConcept<T> +        , WriteableRangeConcept<T> +    { +    }; + +    //! Check if a type T models the RandomAccessRange range concept. +    template<class T> +    struct RandomAccessRangeConcept : BidirectionalRangeConcept<T> +    { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT +        BOOST_RANGE_CONCEPT_ASSERT((RandomAccessIteratorConcept<BOOST_DEDUCED_TYPENAME RandomAccessRangeConcept::iterator>)); +        BOOST_RANGE_CONCEPT_ASSERT((RandomAccessIteratorConcept<BOOST_DEDUCED_TYPENAME RandomAccessRangeConcept::const_iterator>)); +#endif +    }; + +    //! Check if a type T models the WriteableRandomAccessRange range concept. +    template<class T> +    struct WriteableRandomAccessRangeConcept +        : RandomAccessRangeConcept<T> +        , WriteableRangeConcept<T> +    { +    }; + +} // namespace boost + +#endif // BOOST_RANGE_CONCEPTS_HPP diff --git a/3rdParty/Boost/src/boost/range/const_iterator.hpp b/3rdParty/Boost/src/boost/range/const_iterator.hpp index 195f9d4..875320f 100644 --- a/3rdParty/Boost/src/boost/range/const_iterator.hpp +++ b/3rdParty/Boost/src/boost/range/const_iterator.hpp @@ -21,6 +21,7 @@  #include <boost/range/detail/const_iterator.hpp>  #else +#include <boost/range/detail/extract_optional_type.hpp>  #include <boost/type_traits/remove_const.hpp>  #include <cstddef>  #include <utility> @@ -31,11 +32,13 @@ namespace boost      // default      ////////////////////////////////////////////////////////////////////////// +    namespace range_detail { +        BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( const_iterator ) +    } +      template< typename C > -    struct range_const_iterator -    { -        typedef BOOST_DEDUCED_TYPENAME C::const_iterator type; -    }; +    struct range_const_iterator : range_detail::extract_const_iterator<C> +    {};      //////////////////////////////////////////////////////////////////////////      // pair diff --git a/3rdParty/Boost/src/boost/range/detail/extract_optional_type.hpp b/3rdParty/Boost/src/boost/range/detail/extract_optional_type.hpp new file mode 100755 index 0000000..8292e34 --- /dev/null +++ b/3rdParty/Boost/src/boost/range/detail/extract_optional_type.hpp @@ -0,0 +1,52 @@ +// Boost.Range library +// +//  Copyright Arno Schoedl & Neil Groves 2009. +//  Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_EXTRACT_OPTIONAL_TYPE_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_EXTRACT_OPTIONAL_TYPE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/config.hpp> + +#ifdef BOOST_NO_PARTIAL_TEMPLATE_SPECIALIZATION + +#define BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( a_typedef )                         \ +    template< typename C >                                                     \ +    struct extract_ ## a_typedef                                               \ +    {                                                                          \ +        typedef BOOST_DEDUCED_TYPENAME C::a_typedef type;                      \ +    }; + +#else + +namespace boost { +    namespace range_detail { +        template< typename T > struct exists { typedef void type; }; +    } +} + +// Defines extract_some_typedef<T> which exposes T::some_typedef as +// extract_some_typedef<T>::type if T::some_typedef exists. Otherwise +// extract_some_typedef<T> is empty. +#define BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( a_typedef )                         \ +    template< typename C, typename Enable=void >                               \ +    struct extract_ ## a_typedef                                               \ +    {};                                                                        \ +    template< typename C >                                                     \ +    struct extract_ ## a_typedef< C                                            \ +    , BOOST_DEDUCED_TYPENAME boost::range_detail::exists< BOOST_DEDUCED_TYPENAME C::a_typedef >::type \ +    > {                                                                        \ +        typedef BOOST_DEDUCED_TYPENAME C::a_typedef type;                      \ +    }; + +#endif + +#endif // include guard diff --git a/3rdParty/Boost/src/boost/range/detail/implementation_help.hpp b/3rdParty/Boost/src/boost/range/detail/implementation_help.hpp index ca12fa4..1f7d163 100644 --- a/3rdParty/Boost/src/boost/range/detail/implementation_help.hpp +++ b/3rdParty/Boost/src/boost/range/detail/implementation_help.hpp @@ -21,13 +21,13 @@  #include <wchar.h>  #endif -namespace boost  +namespace boost  {      namespace range_detail      {          template <typename T>          inline void boost_range_silence_warning( const T& ) { } -         +          /////////////////////////////////////////////////////////////////////          // end() help          ///////////////////////////////////////////////////////////////////// @@ -36,7 +36,7 @@ namespace boost          {              return s + strlen( s );          } -         +  #ifndef BOOST_NO_CWCHAR          inline const wchar_t* str_end( const wchar_t* s, const wchar_t* )          { @@ -51,7 +51,7 @@ namespace boost                  ;              return s;          } -#endif          +#endif          template< class Char >          inline Char* str_end( Char* s ) @@ -64,7 +64,7 @@ namespace boost          {              return boost_range_array + sz;          } -         +          template< class T, std::size_t sz >          inline const T* array_end( const T BOOST_RANGE_ARRAY_REF()[sz] )          { @@ -74,7 +74,7 @@ namespace boost          /////////////////////////////////////////////////////////////////////          // size() help          ///////////////////////////////////////////////////////////////////// -         +          template< class Char >          inline std::size_t str_size( const Char* const& s )          { @@ -96,7 +96,7 @@ namespace boost          }      } // namespace 'range_detail' -     +  } // namespace 'boost' diff --git a/3rdParty/Boost/src/boost/range/detail/misc_concept.hpp b/3rdParty/Boost/src/boost/range/detail/misc_concept.hpp new file mode 100755 index 0000000..74cb919 --- /dev/null +++ b/3rdParty/Boost/src/boost/range/detail/misc_concept.hpp @@ -0,0 +1,33 @@ +// Boost.Range library concept checks +// +//  Copyright Neil Groves 2009. Use, modification and distribution +//  are subject to the Boost Software License, Version 1.0. (See +//  accompanying file LICENSE_1_0.txt or copy at +//  http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_RANGE_DETAIL_MISC_CONCEPT_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_MISC_CONCEPT_HPP_INCLUDED + +#include <boost/concept_check.hpp> + +namespace boost +{ +    namespace range_detail +    { +        template<typename T1, typename T2> +        class SameTypeConcept +        { +        public: +            BOOST_CONCEPT_USAGE(SameTypeConcept) +            { +                same_type(a,b); +            } +        private: +            template<typename T> void same_type(T,T) {} +            T1 a; +            T2 b; +        }; +    } +} + +#endif // include guard diff --git a/3rdParty/Boost/src/boost/range/iterator.hpp b/3rdParty/Boost/src/boost/range/iterator.hpp index 21798c5..ec73ddc 100644 --- a/3rdParty/Boost/src/boost/range/iterator.hpp +++ b/3rdParty/Boost/src/boost/range/iterator.hpp @@ -25,46 +25,46 @@  namespace boost  { -#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)   - -    namespace range_detail_vc7_1   -    {   -       template< typename C, typename Sig = void(C) >   -       struct range_iterator   -       {   -           typedef BOOST_RANGE_DEDUCED_TYPENAME    -               mpl::eval_if_c< is_const<C>::value,    -                               range_const_iterator< typename remove_const<C>::type >,   -                               range_mutable_iterator<C> >::type type;   -       };   -     -       template< typename C, typename T >   -       struct range_iterator< C, void(T[]) >   -       {   -           typedef T* type;   -       };        -    }   -     -#endif   +#if BOOST_WORKAROUND(BOOST_MSVC, == 1310) + +    namespace range_detail_vc7_1 +    { +       template< typename C, typename Sig = void(C) > +       struct range_iterator +       { +           typedef BOOST_RANGE_DEDUCED_TYPENAME +               mpl::eval_if_c< is_const<C>::value, +                               range_const_iterator< typename remove_const<C>::type >, +                               range_mutable_iterator<C> >::type type; +       }; + +       template< typename C, typename T > +       struct range_iterator< C, void(T[]) > +       { +           typedef T* type; +       }; +    } + +#endif      template< typename C >      struct range_iterator      {  #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) -   -        typedef BOOST_RANGE_DEDUCED_TYPENAME   -               range_detail_vc7_1::range_iterator<C>::type type;   -            -#else   - -        typedef BOOST_RANGE_DEDUCED_TYPENAME  -            mpl::eval_if_c< is_const<C>::value,  + +        typedef BOOST_RANGE_DEDUCED_TYPENAME +               range_detail_vc7_1::range_iterator<C>::type type; + +#else + +        typedef BOOST_RANGE_DEDUCED_TYPENAME +            mpl::eval_if_c< is_const<C>::value,                              range_const_iterator< typename remove_const<C>::type >,                              range_mutable_iterator<C> >::type type; -         -#endif          + +#endif      }; -     +  } // namespace boost  //#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION diff --git a/3rdParty/Boost/src/boost/range/iterator_range.hpp b/3rdParty/Boost/src/boost/range/iterator_range.hpp index d118224..dfcd4d2 100644 --- a/3rdParty/Boost/src/boost/range/iterator_range.hpp +++ b/3rdParty/Boost/src/boost/range/iterator_range.hpp @@ -1,659 +1,16 @@  // Boost.Range library  // -//  Copyright Thorsten Ottosen & Pavol Droba 2003-2004. Use, modification and -//  distribution is subject to the Boost Software License, Version -//  1.0. (See accompanying file LICENSE_1_0.txt or copy at +//  Copyright Neil Groves 2009. +//  Use, modification and distribution is subject to 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)  //  // For more information, see http://www.boost.org/libs/range/  // +#ifndef BOOST_RANGE_ITERATOR_RANGE_HPP_INCLUDED +#define BOOST_RANGE_ITERATOR_RANGE_HPP_INCLUDED -#ifndef BOOST_RANGE_ITERATOR_RANGE_HPP -#define BOOST_RANGE_ITERATOR_RANGE_HPP - -#include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate. -#include <boost/detail/workaround.hpp> - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) -    #pragma warning( push ) -    #pragma warning( disable : 4996 ) -#endif - -// From boost/dynamic_bitset.hpp; thanks to Matthias Troyer for Cray X1 patch. -#ifndef BOOST_OLD_IOSTREAMS  -# if defined(__STL_CONFIG_H) && \ -    !defined (__STL_USE_NEW_IOSTREAMS) && !defined(__crayx1) \ -    /**/ -#  define BOOST_OLD_IOSTREAMS -# endif -#endif // #ifndef BOOST_OLD_IOSTREAMS - -#include <boost/assert.hpp> -#include <boost/iterator/iterator_traits.hpp>     -#include <boost/type_traits/is_abstract.hpp> -#include <boost/range/functions.hpp> -#include <boost/range/iterator.hpp> -#include <boost/range/difference_type.hpp> -#include <boost/utility/enable_if.hpp> -#include <iterator> -#include <algorithm> -#ifndef _STLP_NO_IOSTREAMS -# ifndef BOOST_OLD_IOSTREAMS -#  include <ostream> -# else -#  include <ostream.h> -# endif -#endif // _STLP_NO_IOSTREAMS -#include <cstddef> - -/*! \file -    Defines the \c iterator_class and related functions.  -    \c iterator_range is a simple wrapper of iterator pair idiom. It provides -    a rich subset of Container interface. -*/ - - -namespace boost  -{ -    namespace iterator_range_detail -    { -        // -        // The functions adl_begin and adl_end are implemented in a separate -        // class for gcc-2.9x -        // -        template<typename IteratorT> -        struct iterator_range_impl { -            template< class ForwardRange > -            static IteratorT adl_begin( ForwardRange& r ) -            { -                return IteratorT( boost::begin( r ) ); -            } -             -            template< class ForwardRange > -            static IteratorT adl_end( ForwardRange& r ) -            { -                return IteratorT( boost::end( r ) ); -            } -        }; -  -        template< class Left, class Right > -        inline bool equal( const Left& l, const Right& r ) -        { -            typedef BOOST_DEDUCED_TYPENAME boost::range_difference<Left>::type sz_type; - -            sz_type l_size = boost::distance( l ), -                    r_size = boost::distance( r ); - -            if( l_size != r_size ) -                return false; - -            return std::equal( boost::begin(l), boost::end(l),  -                               boost::begin(r) );                 -        } - -        template< class Left, class Right > -        inline bool less_than( const Left& l, const Right& r ) -        {                 -            return std::lexicographical_compare( boost::begin(l),  -                                                 boost::end(l),  -                                                 boost::begin(r),  -                                                 boost::end(r) );                 -        } -            -        struct range_tag { }; -        struct const_range_tag { }; - -    } - -//  iterator range template class -----------------------------------------// - -        //! iterator_range class -        /*! -            An \c iterator_range delimits a range in a sequence by beginning and ending iterators.  -            An iterator_range can be passed to an algorithm which requires a sequence as an input.  -            For example, the \c toupper() function may be used most frequently on strings,  -            but can also be used on iterator_ranges:  -             -            \code -                boost::tolower( find( s, "UPPERCASE STRING" ) ); -            \endcode - -            Many algorithms working with sequences take a pair of iterators,  -            delimiting a working range, as an arguments. The \c iterator_range class is an  -            encapsulation of a range identified by a pair of iterators.  -            It provides a collection interface,  -            so it is possible to pass an instance to an algorithm requiring a collection as an input.  -        */ -        template<typename IteratorT>  -        class iterator_range -        { -        protected: // Used by sub_range -            //! implementation class -            typedef iterator_range_detail::iterator_range_impl<IteratorT> impl; -        public: - -            //! this type -            typedef iterator_range<IteratorT> type; -            //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type); -         -            //! Encapsulated value type -            typedef BOOST_DEDUCED_TYPENAME  -                iterator_value<IteratorT>::type value_type; - -            //! Difference type -            typedef BOOST_DEDUCED_TYPENAME  -                iterator_difference<IteratorT>::type difference_type; -             -            //! Size type -            typedef std::size_t size_type; // note: must be unsigned - -            //! This type -            typedef iterator_range<IteratorT> this_type; - -            //! Refence type -            // -            // Needed because value-type is the same for  -            // const and non-const iterators -            // -            typedef BOOST_DEDUCED_TYPENAME -                iterator_reference<IteratorT>::type reference; -             -            //! const_iterator type -            /*!  -                There is no distinction between const_iterator and iterator. -                These typedefs are provides to fulfill container interface -            */  -            typedef IteratorT const_iterator; -            //! iterator type -            typedef IteratorT iterator; - -        private: // for return value of operator()() -            typedef BOOST_DEDUCED_TYPENAME  -                boost::mpl::if_< boost::is_abstract<value_type>, -                                 reference, value_type >::type abstract_value_type; - -        public: -            iterator_range() : m_Begin( iterator() ), m_End( iterator() ) -                #ifndef NDEBUG -            , singular( true ) -                #endif -            { } -            -            //! Constructor from a pair of iterators -            template< class Iterator > -            iterator_range( Iterator Begin, Iterator End ) :  -                m_Begin(Begin), m_End(End) -                #ifndef NDEBUG -            , singular(false)  -                #endif -            {} - -            //! Constructor from a Range -            template< class Range > -            iterator_range( const Range& r ) :  -                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) -                #ifndef NDEBUG -            , singular(false)  -                #endif -            {} -             -            //! Constructor from a Range -            template< class Range > -            iterator_range( Range& r ) :  -                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) -                #ifndef NDEBUG -            , singular(false)  -                #endif -            {} - -            //! Constructor from a Range -            template< class Range > -            iterator_range( const Range& r, iterator_range_detail::const_range_tag ) :  -                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) -                #ifndef NDEBUG -            , singular(false)  -                #endif -            {} - -            //! Constructor from a Range -            template< class Range > -            iterator_range( Range& r, iterator_range_detail::range_tag ) :  -                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) -                #ifndef NDEBUG -            , singular(false)  -                #endif -            {} - -            #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) -            this_type& operator=( const this_type& r )     -            { -                m_Begin  = r.begin();  -                m_End    = r.end(); - -                #ifndef NDEBUG -                singular = r.singular; -                #endif -                return *this; -            } -            #endif -                 -            template< class Iterator > -            iterator_range& operator=( const iterator_range<Iterator>& r )     -            { -                m_Begin  = r.begin();  -                m_End    = r.end(); -                #ifndef NDEBUG -                singular = r.is_singular(); -                #endif -                return *this; -            } -                                       -            template< class ForwardRange > -            iterator_range& operator=( ForwardRange& r ) -            { -                m_Begin  = impl::adl_begin( r );  -                m_End    = impl::adl_end( r ); -                #ifndef NDEBUG -                singular = false; -                #endif -                return *this; -            } - -            template< class ForwardRange > -            iterator_range& operator=( const ForwardRange& r ) -            { -                m_Begin  = impl::adl_begin( r );  -                m_End    = impl::adl_end( r ); -                #ifndef NDEBUG     -                singular = false; -                #endif -                return *this; -            } - -            IteratorT begin() const  -            {  -                BOOST_ASSERT( !is_singular() ); -                return m_Begin;  -            } - -            IteratorT end() const  -            {  -                BOOST_ASSERT( !is_singular() ); -                return m_End;  -            }  - -            difference_type size() const -            {  -                BOOST_ASSERT( !is_singular() ); -                return m_End - m_Begin; -            } -             -            bool empty() const -            { -                BOOST_ASSERT( !is_singular() ); -                return m_Begin == m_End; -            } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))   -            operator bool() const -            { -                return !empty(); -            }                                     -#else             -            typedef iterator (iterator_range::*unspecified_bool_type) () const; -            operator unspecified_bool_type() const -            { -                return empty() ? 0: &iterator_range::end; -            } -#endif - -            bool equal( const iterator_range& r ) const -            { -                BOOST_ASSERT( !is_singular() ); -                return m_Begin == r.m_Begin && m_End == r.m_End; -            } - - -#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -            bool operator==( const iterator_range& r ) const -            { -                BOOST_ASSERT( !is_singular() ); -                return iterator_range_detail::equal( *this, r ); -            } - -            bool operator!=( const iterator_range& r ) const -            { -                BOOST_ASSERT( !is_singular() ); -                return !operator==(r); -            } - -           bool operator<( const iterator_range& r ) const -           { -               BOOST_ASSERT( !is_singular() ); -               return iterator_range_detail::less_than( *this, r ); -           } - -#endif             - -        public: // convenience -           reference front() const -           { -               BOOST_ASSERT( !empty() ); -               return *m_Begin; -           } -     -           reference back() const -           { -               BOOST_ASSERT( !empty() ); -               IteratorT last( m_End ); -               return *--last; -           } -     -           reference operator[]( difference_type at ) const -           { -               BOOST_ASSERT( at >= 0 && at < size() ); -               return m_Begin[at]; -           } - -           // -           // When storing transform iterators, operator[]() -           // fails because it returns by reference. Therefore -           // operator()() is provided for these cases. -           //  -           abstract_value_type operator()( difference_type at ) const                               -           { -               BOOST_ASSERT( at >= 0 && at < size() ); -               return m_Begin[at];                -           } - -           iterator_range& advance_begin( difference_type n ) -           { -               BOOST_ASSERT( !is_singular() ); -               std::advance( m_Begin, n ); -               return *this; -           } -            -           iterator_range& advance_end( difference_type n ) -           { -               BOOST_ASSERT( !is_singular() ); -               std::advance( m_End, n ); -               return *this; -           } -            -        private: -            // begin and end iterators -            IteratorT m_Begin; -            IteratorT m_End; - -            #ifndef NDEBUG -            bool      singular; -            #endif - -        public: -            bool is_singular() const -            { -                 #ifndef NDEBUG -                 return singular; -                 #else -                 return false; -                 #endif -            } - -        protected: -            // -            // Allow subclasses an easy way to access the -            // base type -            // -            typedef iterator_range iterator_range_; -        }; - -//  iterator range free-standing operators ---------------------------// - -#ifndef _STLP_NO_IOSTREAMS -# ifndef BOOST_OLD_IOSTREAMS    - -        //! iterator_range output operator -        /*! -            Output the range to an ostream. Elements are outputed -            in a sequence without separators. -        */ -        template< typename IteratorT, typename Elem, typename Traits > -        inline std::basic_ostream<Elem,Traits>& operator<<(  -                    std::basic_ostream<Elem, Traits>& Os, -                    const iterator_range<IteratorT>& r ) -        { -            std::copy( r.begin(), r.end(),  -                       std::ostream_iterator< BOOST_DEDUCED_TYPENAME  -                                              iterator_value<IteratorT>::type,  -                                              Elem, Traits>(Os) ); -            return Os; -        } - -# else - -        //! iterator_range output operator -        /*! -            Output the range to an ostream. Elements are outputed -            in a sequence without separators. -        */ -        template< typename IteratorT > -        inline std::ostream& operator<<(  -                    std::ostream& Os, -                    const iterator_range<IteratorT>& r ) -        { -            std::copy( r.begin(), r.end(), std::ostream_iterator<char>(Os)); -            return Os; -        } - -# endif -#endif // _STLP_NO_IOSTREAMS - -        ///////////////////////////////////////////////////////////////////// -        // comparison operators -        ///////////////////////////////////////////////////////////////////// - -        template< class IteratorT, class ForwardRange > -        inline bool operator==( const ForwardRange& l,  -                                const iterator_range<IteratorT>& r ) -        { -            return iterator_range_detail::equal( l, r ); -        } - -        template< class IteratorT, class ForwardRange > -        inline bool operator!=( const ForwardRange& l,  -                                const iterator_range<IteratorT>& r ) -        { -            return !iterator_range_detail::equal( l, r ); -        } - -        template< class IteratorT, class ForwardRange > -        inline bool operator<( const ForwardRange& l,  -                               const iterator_range<IteratorT>& r ) -        { -            return iterator_range_detail::less_than( l, r ); -        } - -#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING -#else -        template< class Iterator1T, class Iterator2T > -        inline bool operator==( const iterator_range<Iterator1T>& l,  -                                const iterator_range<Iterator2T>& r ) -        { -            return iterator_range_detail::equal( l, r ); -        } - -        template< class IteratorT, class ForwardRange > -        inline bool operator==( const iterator_range<IteratorT>& l,  -                                const ForwardRange& r ) -        { -            return iterator_range_detail::equal( l, r ); -        } - - -        template< class Iterator1T, class Iterator2T > -        inline bool operator!=( const iterator_range<Iterator1T>& l,  -                                const iterator_range<Iterator2T>& r ) -        { -            return !iterator_range_detail::equal( l, r ); -        } -         -        template< class IteratorT, class ForwardRange > -        inline bool operator!=( const iterator_range<IteratorT>& l,  -                                const ForwardRange& r ) -        { -            return !iterator_range_detail::equal( l, r ); -        } - -         -        template< class Iterator1T, class Iterator2T > -        inline bool operator<( const iterator_range<Iterator1T>& l,  -                               const iterator_range<Iterator2T>& r ) -        { -            return iterator_range_detail::less_than( l, r ); -        } - -        template< class IteratorT, class ForwardRange > -        inline bool operator<( const iterator_range<IteratorT>& l,  -                               const ForwardRange& r ) -        {             -            return iterator_range_detail::less_than( l, r ); -        } - -#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING -                     -//  iterator range utilities -----------------------------------------// - -        //! iterator_range construct helper  -        /*! -            Construct an \c iterator_range from a pair of iterators - -            \param Begin A begin iterator -            \param End An end iterator -            \return iterator_range object -        */ -        template< typename IteratorT > -        inline iterator_range< IteratorT >  -        make_iterator_range( IteratorT Begin, IteratorT End )  -        {    -            return iterator_range<IteratorT>( Begin, End ); -        } -                      -#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -        template< typename Range > -        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > -        make_iterator_range( Range& r )  -        {    -            return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > -                ( boost::begin( r ), boost::end( r ) ); -        } -         -#else -        //! iterator_range construct helper -        /*! -            Construct an \c iterator_range from a \c Range containing the begin -            and end iterators. -        */ -        template< class ForwardRange > -        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > -        make_iterator_range( ForwardRange& r )  -        {    -           return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > -                ( r, iterator_range_detail::range_tag() ); -        } - -        template< class ForwardRange > -        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > -        make_iterator_range( const ForwardRange& r )  -        {    -           return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > -                ( r, iterator_range_detail::const_range_tag() ); -        } - -#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -        namespace iterator_range_detail -        {     -            template< class Range > -            inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > -            make_range_impl( Range& r,  -                             BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, -                             BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) -            { -                // -                // Not worth the effort -                // -                //if( advance_begin == 0 && advance_end == 0 ) -                //    return make_iterator_range( r ); -                // - -                BOOST_DEDUCED_TYPENAME range_iterator<Range>::type  -                    new_begin = boost::begin( r ), -                    new_end   = boost::end( r ); -                std::advance( new_begin, advance_begin ); -                std::advance( new_end, advance_end ); -                return make_iterator_range( new_begin, new_end ); -            } -        } -         -#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -        template< class Range > -        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > -        make_iterator_range( Range& r,  -                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, -                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) -        { -            //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); -            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); -        } - -#else - -        template< class Range > -        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > -        make_iterator_range( Range& r,  -                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, -                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) -        { -            //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); -            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); -        } - -        template< class Range > -        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type > -        make_iterator_range( const Range& r,  -                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, -                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) -        { -            //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); -            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); -        } - -#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -        //! copy a range into a sequence -        /*! -            Construct a new sequence of the specified type from the elements -            in the given range - -            \param Range An input range -            \return New sequence -        */ -        template< typename SeqT, typename Range > -        inline SeqT copy_range( const Range& r ) -        { -            return SeqT( boost::begin( r ), boost::end( r ) ); -        } - -} // namespace 'boost' - -#undef BOOST_OLD_IOSTREAMS - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))  -    #pragma warning( pop ) -#endif - -#endif +#include "boost/range/iterator_range_core.hpp" +#include "boost/range/iterator_range_io.hpp" +#endif // include guard diff --git a/3rdParty/Boost/src/boost/range/iterator_range_core.hpp b/3rdParty/Boost/src/boost/range/iterator_range_core.hpp new file mode 100755 index 0000000..497b1e3 --- /dev/null +++ b/3rdParty/Boost/src/boost/range/iterator_range_core.hpp @@ -0,0 +1,542 @@ +// Boost.Range library +// +//  Copyright Neil Groves & Thorsten Ottosen & Pavol Droba 2003-2004. +//  Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED +#define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED + +#include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate. +#include <boost/detail/workaround.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) +    #pragma warning( push ) +    #pragma warning( disable : 4996 ) +#endif + +#include <boost/assert.hpp> +#include <boost/iterator/iterator_traits.hpp> +#include <boost/iterator/iterator_facade.hpp> +#include <boost/type_traits/is_abstract.hpp> +#include <boost/type_traits/is_pointer.hpp> +#include <boost/range/functions.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/difference_type.hpp> +#include <boost/range/algorithm/equal.hpp> +#include <boost/utility/enable_if.hpp> +#include <iterator> +#include <algorithm> +#include <cstddef> + +/*! \file +    Defines the \c iterator_class and related functions. +    \c iterator_range is a simple wrapper of iterator pair idiom. It provides +    a rich subset of Container interface. +*/ + + +namespace boost +{ +    namespace iterator_range_detail +    { +        // +        // The functions adl_begin and adl_end are implemented in a separate +        // class for gcc-2.9x +        // +        template<class IteratorT> +        struct iterator_range_impl { +            template< class ForwardRange > +            static IteratorT adl_begin( ForwardRange& r ) +            { +                return IteratorT( boost::begin( r ) ); +            } + +            template< class ForwardRange > +            static IteratorT adl_end( ForwardRange& r ) +            { +                return IteratorT( boost::end( r ) ); +            } +        }; + +        template< class Left, class Right > +        inline bool less_than( const Left& l, const Right& r ) +        { +            return std::lexicographical_compare( boost::begin(l), +                                                 boost::end(l), +                                                 boost::begin(r), +                                                 boost::end(r) ); +        } + +        // This version is maintained since it is used in other boost libraries +        // such as Boost.Assign +        template< class Left, class Right > +        inline bool equal(const Left& l, const Right& r) +        { +            return boost::equal(l, r); +        } + +        struct range_tag { }; +        struct const_range_tag { }; + +    } + +//  iterator range template class -----------------------------------------// + +        //! iterator_range class +        /*! +            An \c iterator_range delimits a range in a sequence by beginning and ending iterators. +            An iterator_range can be passed to an algorithm which requires a sequence as an input. +            For example, the \c toupper() function may be used most frequently on strings, +            but can also be used on iterator_ranges: + +            \code +                boost::tolower( find( s, "UPPERCASE STRING" ) ); +            \endcode + +            Many algorithms working with sequences take a pair of iterators, +            delimiting a working range, as an arguments. The \c iterator_range class is an +            encapsulation of a range identified by a pair of iterators. +            It provides a collection interface, +            so it is possible to pass an instance to an algorithm requiring a collection as an input. +        */ +        template<class IteratorT> +        class iterator_range +        { +        protected: // Used by sub_range +            //! implementation class +            typedef iterator_range_detail::iterator_range_impl<IteratorT> impl; +        public: + +            //! this type +            typedef iterator_range<IteratorT> type; +            //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type); + +            //! Encapsulated value type +            typedef BOOST_DEDUCED_TYPENAME +                iterator_value<IteratorT>::type value_type; + +            //! Difference type +            typedef BOOST_DEDUCED_TYPENAME +                iterator_difference<IteratorT>::type difference_type; + +            //! Size type +            typedef std::size_t size_type; // note: must be unsigned + +            //! This type +            typedef iterator_range<IteratorT> this_type; + +            //! Reference type +            // +            // Needed because value-type is the same for +            // const and non-const iterators +            // +            typedef BOOST_DEDUCED_TYPENAME +                iterator_reference<IteratorT>::type reference; + +            //! const_iterator type +            /*! +                There is no distinction between const_iterator and iterator. +                These typedefs are provides to fulfill container interface +            */ +            typedef IteratorT const_iterator; +            //! iterator type +            typedef IteratorT iterator; + +        private: // for return value of operator()() +            typedef BOOST_DEDUCED_TYPENAME +                boost::mpl::if_< boost::is_abstract<value_type>, +                                 reference, value_type >::type abstract_value_type; + +        public: +            iterator_range() : m_Begin( iterator() ), m_End( iterator() ) +            { } + +            //! Constructor from a pair of iterators +            template< class Iterator > +            iterator_range( Iterator Begin, Iterator End ) : +                m_Begin(Begin), m_End(End) +            {} + +            //! Constructor from a Range +            template< class Range > +            iterator_range( const Range& r ) : +                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) +            {} + +            //! Constructor from a Range +            template< class Range > +            iterator_range( Range& r ) : +                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) +            {} + +            //! Constructor from a Range +            template< class Range > +            iterator_range( const Range& r, iterator_range_detail::const_range_tag ) : +                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) +            {} + +            //! Constructor from a Range +            template< class Range > +            iterator_range( Range& r, iterator_range_detail::range_tag ) : +                m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) +            {} + +            #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +            this_type& operator=( const this_type& r ) +            { +                m_Begin  = r.begin(); +                m_End    = r.end(); +                return *this; +            } +            #endif + +            template< class Iterator > +            iterator_range& operator=( const iterator_range<Iterator>& r ) +            { +                m_Begin  = r.begin(); +                m_End    = r.end(); +                return *this; +            } + +            template< class ForwardRange > +            iterator_range& operator=( ForwardRange& r ) +            { +                m_Begin  = impl::adl_begin( r ); +                m_End    = impl::adl_end( r ); +                return *this; +            } + +            template< class ForwardRange > +            iterator_range& operator=( const ForwardRange& r ) +            { +                m_Begin  = impl::adl_begin( r ); +                m_End    = impl::adl_end( r ); +                return *this; +            } + +            IteratorT begin() const +            { +                return m_Begin; +            } + +            IteratorT end() const +            { +                return m_End; +            } + +            difference_type size() const +            { +                return m_End - m_Begin; +            } + +            bool empty() const +            { +                return m_Begin == m_End; +            } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +            operator bool() const +            { +                return !empty(); +            } +#else +            typedef iterator (iterator_range::*unspecified_bool_type) () const; +            operator unspecified_bool_type() const +            { +                return empty() ? 0: &iterator_range::end; +            } +#endif + +            bool equal( const iterator_range& r ) const +            { +                return m_Begin == r.m_Begin && m_End == r.m_End; +            } + + +#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +            bool operator==( const iterator_range& r ) const +            { +                return boost::equal( *this, r ); +            } + +            bool operator!=( const iterator_range& r ) const +            { +                return !operator==(r); +            } + +           bool operator<( const iterator_range& r ) const +           { +               return iterator_range_detail::less_than( *this, r ); +           } + +#endif + +        public: // convenience +           reference front() const +           { +               BOOST_ASSERT( !empty() ); +               return *m_Begin; +           } + +           reference back() const +           { +               BOOST_ASSERT( !empty() ); +               IteratorT last( m_End ); +               return *--last; +           } + +           reference operator[]( difference_type at ) const +           { +               BOOST_ASSERT( at >= 0 && at < size() ); +               return m_Begin[at]; +           } + +           // +           // When storing transform iterators, operator[]() +           // fails because it returns by reference. Therefore +           // operator()() is provided for these cases. +           // +           abstract_value_type operator()( difference_type at ) const +           { +               BOOST_ASSERT( at >= 0 && at < size() ); +               return m_Begin[at]; +           } + +           iterator_range& advance_begin( difference_type n ) +           { +               std::advance( m_Begin, n ); +               return *this; +           } + +           iterator_range& advance_end( difference_type n ) +           { +               std::advance( m_End, n ); +               return *this; +           } + +        private: +            // begin and end iterators +            IteratorT m_Begin; +            IteratorT m_End; + +        protected: +            // +            // Allow subclasses an easy way to access the +            // base type +            // +            typedef iterator_range iterator_range_; +        }; + +//  iterator range free-standing operators ---------------------------// + +        ///////////////////////////////////////////////////////////////////// +        // comparison operators +        ///////////////////////////////////////////////////////////////////// + +        template< class IteratorT, class ForwardRange > +        inline bool operator==( const ForwardRange& l, +                                const iterator_range<IteratorT>& r ) +        { +            return boost::equal( l, r ); +        } + +        template< class IteratorT, class ForwardRange > +        inline bool operator!=( const ForwardRange& l, +                                const iterator_range<IteratorT>& r ) +        { +            return !boost::equal( l, r ); +        } + +        template< class IteratorT, class ForwardRange > +        inline bool operator<( const ForwardRange& l, +                               const iterator_range<IteratorT>& r ) +        { +            return iterator_range_detail::less_than( l, r ); +        } + +#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +#else +        template< class Iterator1T, class Iterator2T > +        inline bool operator==( const iterator_range<Iterator1T>& l, +                                const iterator_range<Iterator2T>& r ) +        { +            return boost::equal( l, r ); +        } + +        template< class IteratorT, class ForwardRange > +        inline bool operator==( const iterator_range<IteratorT>& l, +                                const ForwardRange& r ) +        { +            return boost::equal( l, r ); +        } + + +        template< class Iterator1T, class Iterator2T > +        inline bool operator!=( const iterator_range<Iterator1T>& l, +                                const iterator_range<Iterator2T>& r ) +        { +            return !boost::equal( l, r ); +        } + +        template< class IteratorT, class ForwardRange > +        inline bool operator!=( const iterator_range<IteratorT>& l, +                                const ForwardRange& r ) +        { +            return !boost::equal( l, r ); +        } + + +        template< class Iterator1T, class Iterator2T > +        inline bool operator<( const iterator_range<Iterator1T>& l, +                               const iterator_range<Iterator2T>& r ) +        { +            return iterator_range_detail::less_than( l, r ); +        } + +        template< class IteratorT, class ForwardRange > +        inline bool operator<( const iterator_range<IteratorT>& l, +                               const ForwardRange& r ) +        { +            return iterator_range_detail::less_than( l, r ); +        } + +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +//  iterator range utilities -----------------------------------------// + +        //! iterator_range construct helper +        /*! +            Construct an \c iterator_range from a pair of iterators + +            \param Begin A begin iterator +            \param End An end iterator +            \return iterator_range object +        */ +        template< typename IteratorT > +        inline iterator_range< IteratorT > +        make_iterator_range( IteratorT Begin, IteratorT End ) +        { +            return iterator_range<IteratorT>( Begin, End ); +        } + +#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +        template< typename Range > +        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > +        make_iterator_range( Range& r ) +        { +            return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > +                ( boost::begin( r ), boost::end( r ) ); +        } + +#else +        //! iterator_range construct helper +        /*! +            Construct an \c iterator_range from a \c Range containing the begin +            and end iterators. +        */ +        template< class ForwardRange > +        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > +        make_iterator_range( ForwardRange& r ) +        { +           return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > +                ( r, iterator_range_detail::range_tag() ); +        } + +        template< class ForwardRange > +        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > +        make_iterator_range( const ForwardRange& r ) +        { +           return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > +                ( r, iterator_range_detail::const_range_tag() ); +        } + +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +        namespace iterator_range_detail +        { +            template< class Range > +            inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > +            make_range_impl( Range& r, +                             BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, +                             BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) +            { +                // +                // Not worth the effort +                // +                //if( advance_begin == 0 && advance_end == 0 ) +                //    return make_iterator_range( r ); +                // + +                BOOST_DEDUCED_TYPENAME range_iterator<Range>::type +                    new_begin = boost::begin( r ), +                    new_end   = boost::end( r ); +                std::advance( new_begin, advance_begin ); +                std::advance( new_end, advance_end ); +                return make_iterator_range( new_begin, new_end ); +            } +        } + +#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +        template< class Range > +        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > +        make_iterator_range( Range& r, +                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, +                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) +        { +            //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); +            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); +        } + +#else + +        template< class Range > +        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > +        make_iterator_range( Range& r, +                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, +                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) +        { +            //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); +            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); +        } + +        template< class Range > +        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type > +        make_iterator_range( const Range& r, +                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, +                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) +        { +            //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); +            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); +        } + +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +        //! copy a range into a sequence +        /*! +            Construct a new sequence of the specified type from the elements +            in the given range + +            \param Range An input range +            \return New sequence +        */ +        template< typename SeqT, typename Range > +        inline SeqT copy_range( const Range& r ) +        { +            return SeqT( boost::begin( r ), boost::end( r ) ); +        } + +} // namespace 'boost' + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) +    #pragma warning( pop ) +#endif + +#endif + diff --git a/3rdParty/Boost/src/boost/range/iterator_range_io.hpp b/3rdParty/Boost/src/boost/range/iterator_range_io.hpp new file mode 100755 index 0000000..51e3a4f --- /dev/null +++ b/3rdParty/Boost/src/boost/range/iterator_range_io.hpp @@ -0,0 +1,93 @@ +// Boost.Range library +// +//  Copyright Neil Groves 2009. +//  Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ITERATOR_RANGE_IO_HPP_INCLUDED +#define BOOST_RANGE_ITERATOR_RANGE_IO_HPP_INCLUDED + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) +    #pragma warning( push ) +    #pragma warning( disable : 4996 ) +#endif + +// From boost/dynamic_bitset.hpp; thanks to Matthias Troyer for Cray X1 patch. +#ifndef BOOST_OLD_IOSTREAMS  +# if defined(__STL_CONFIG_H) && \ +    !defined (__STL_USE_NEW_IOSTREAMS) && !defined(__crayx1) \ +    /**/ +#  define BOOST_OLD_IOSTREAMS +# endif +#endif // #ifndef BOOST_OLD_IOSTREAMS + +#ifndef _STLP_NO_IOSTREAMS +# ifndef BOOST_OLD_IOSTREAMS +#  include <ostream> +# else +#  include <ostream.h> +# endif +#endif // _STLP_NO_IOSTREAMS + +#include <boost/range/iterator_range_core.hpp> +#include <iterator> +#include <algorithm> +#include <cstddef> + +namespace boost +{ + +#ifndef _STLP_NO_IOSTREAMS +# ifndef BOOST_OLD_IOSTREAMS    + +        //! iterator_range output operator +        /*! +            Output the range to an ostream. Elements are outputed +            in a sequence without separators. +        */ +        template< typename IteratorT, typename Elem, typename Traits > +        inline std::basic_ostream<Elem,Traits>& operator<<(  +                    std::basic_ostream<Elem, Traits>& Os, +                    const iterator_range<IteratorT>& r ) +        { +            std::copy( r.begin(), r.end(),  +                       std::ostream_iterator< BOOST_DEDUCED_TYPENAME  +                                              iterator_value<IteratorT>::type,  +                                              Elem, Traits>(Os) ); +            return Os; +        } + +# else + +        //! iterator_range output operator +        /*! +            Output the range to an ostream. Elements are outputed +            in a sequence without separators. +        */ +        template< typename IteratorT > +        inline std::ostream& operator<<(  +                    std::ostream& Os, +                    const iterator_range<IteratorT>& r ) +        { +            std::copy( r.begin(), r.end(), std::ostream_iterator<char>(Os)); +            return Os; +        } + +# endif +#endif // _STLP_NO_IOSTREAMS + +} // namespace boost + +#undef BOOST_OLD_IOSTREAMS + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) +    #pragma warning(pop) +#endif + +#endif // include guard diff --git a/3rdParty/Boost/src/boost/range/mutable_iterator.hpp b/3rdParty/Boost/src/boost/range/mutable_iterator.hpp index 2f45c16..7beca66 100644 --- a/3rdParty/Boost/src/boost/range/mutable_iterator.hpp +++ b/3rdParty/Boost/src/boost/range/mutable_iterator.hpp @@ -21,6 +21,7 @@  #include <boost/range/detail/iterator.hpp>  #else +#include <boost/range/detail/extract_optional_type.hpp>  #include <boost/iterator/iterator_traits.hpp>  #include <cstddef>  #include <utility> @@ -31,11 +32,13 @@ namespace boost      // default      ////////////////////////////////////////////////////////////////////////// +    namespace range_detail { +        BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( iterator ) +    } +      template< typename C > -    struct range_mutable_iterator -    { -        typedef BOOST_DEDUCED_TYPENAME C::iterator type; -    }; +    struct range_mutable_iterator : range_detail::extract_iterator<C> +    {};      //////////////////////////////////////////////////////////////////////////      // pair diff --git a/3rdParty/Boost/src/boost/range/size.hpp b/3rdParty/Boost/src/boost/range/size.hpp index 311a692..2b572d4 100644 --- a/3rdParty/Boost/src/boost/range/size.hpp +++ b/3rdParty/Boost/src/boost/range/size.hpp @@ -20,7 +20,7 @@  #include <boost/range/difference_type.hpp>  #include <boost/assert.hpp> -namespace boost  +namespace boost  {      template< class T > diff --git a/3rdParty/Boost/src/boost/range/size_type.hpp b/3rdParty/Boost/src/boost/range/size_type.hpp index 7ed8dfa..8c184f8 100644 --- a/3rdParty/Boost/src/boost/range/size_type.hpp +++ b/3rdParty/Boost/src/boost/range/size_type.hpp @@ -67,7 +67,8 @@ namespace boost      { };      template< class T > -    struct range_size<const T > : range_size<T> +    struct range_size<const T > +        : detail::range_size<T>      { };  } // namespace boost diff --git a/3rdParty/Boost/src/boost/smart_ptr/detail/sp_convertible.hpp b/3rdParty/Boost/src/boost/smart_ptr/detail/sp_convertible.hpp index b7f0ea8..fe44069 100644 --- a/3rdParty/Boost/src/boost/smart_ptr/detail/sp_convertible.hpp +++ b/3rdParty/Boost/src/boost/smart_ptr/detail/sp_convertible.hpp @@ -25,7 +25,7 @@  # define BOOST_SP_NO_SP_CONVERTIBLE  #endif -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x620 ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x630 )  # define BOOST_SP_NO_SP_CONVERTIBLE  #endif diff --git a/3rdParty/Boost/src/boost/thread/barrier.hpp b/3rdParty/Boost/src/boost/thread/barrier.hpp index 546f5e9..4ca30cb 100644 --- a/3rdParty/Boost/src/boost/thread/barrier.hpp +++ b/3rdParty/Boost/src/boost/thread/barrier.hpp @@ -9,6 +9,7 @@  #define BOOST_BARRIER_JDM030602_HPP  #include <boost/thread/detail/config.hpp> +#include <boost/throw_exception.hpp>  #include <boost/thread/mutex.hpp>  #include <boost/thread/condition_variable.hpp> @@ -27,7 +28,7 @@ namespace boost              : m_threshold(count), m_count(count), m_generation(0)          {              if (count == 0) -                throw std::invalid_argument("count cannot be zero."); +                boost::throw_exception(std::invalid_argument("count cannot be zero."));          }          bool wait() diff --git a/3rdParty/Boost/src/boost/thread/detail/thread.hpp b/3rdParty/Boost/src/boost/thread/detail/thread.hpp index 170801b..9615a39 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread.hpp @@ -39,10 +39,13 @@ namespace boost              public detail::thread_data_base          {          public: -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES              thread_data(F&& f_):                  f(static_cast<F&&>(f_))              {} +            thread_data(F& f_): +                f(f_) +            {}  #else              thread_data(F f_):                  f(f_) @@ -119,7 +122,7 @@ namespace boost          detail::thread_data_ptr get_thread_info() const; -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          template<typename F>          static inline detail::thread_data_ptr make_thread_info(F&& f)          { @@ -127,7 +130,7 @@ namespace boost          }          static inline detail::thread_data_ptr make_thread_info(void (*f)())          { -            return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f)); +            return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f)));          }  #else          template<typename F> @@ -141,8 +144,8 @@ namespace boost              return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));          } -        struct dummy;  #endif +        struct dummy;      public:  #ifdef __SUNPRO_CC           thread(const volatile thread&);  @@ -150,13 +153,22 @@ namespace boost          thread();          ~thread(); -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES +#ifdef BOOST_MSVC +        template <class F> +        explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0): +            thread_info(make_thread_info(f)) +        { +            start_thread(); +        } +#else          template <class F>          thread(F&& f):              thread_info(make_thread_info(static_cast<F&&>(f)))          {              start_thread();          } +#endif          thread(thread&& other)          { @@ -343,10 +355,14 @@ namespace boost          return lhs.swap(rhs);      } -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES +    inline thread&& move(thread& t) +    { +        return static_cast<thread&&>(t); +    }      inline thread&& move(thread&& t)      { -        return t; +        return static_cast<thread&&>(t);      }  #else      inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t) @@ -445,7 +461,7 @@ namespace boost          {              virtual ~thread_exit_function_base()              {} -            virtual void operator()() const=0; +            virtual void operator()()=0;          };          template<typename F> @@ -458,13 +474,13 @@ namespace boost                  f(f_)              {} -            void operator()() const +            void operator()()              {                  f();              }          }; -        void add_thread_exit_function(thread_exit_function_base*); +        void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);      }      namespace this_thread diff --git a/3rdParty/Boost/src/boost/thread/future.hpp b/3rdParty/Boost/src/boost/thread/future.hpp index 3d694eb..8111d9e 100644 --- a/3rdParty/Boost/src/boost/thread/future.hpp +++ b/3rdParty/Boost/src/boost/thread/future.hpp @@ -1,4 +1,4 @@ -//  (C) Copyright 2008-9 Anthony Williams  +//  (C) Copyright 2008-10 Anthony Williams   //  //  Distributed under the Boost Software License, Version 1.0. (See  //  accompanying file LICENSE_1_0.txt or copy at @@ -16,6 +16,7 @@  #include <boost/type_traits/is_convertible.hpp>  #include <boost/mpl/if.hpp>  #include <boost/config.hpp> +#include <boost/throw_exception.hpp>  #include <algorithm>  #include <boost/function.hpp>  #include <boost/bind.hpp> @@ -218,7 +219,7 @@ namespace boost          struct future_traits          {              typedef boost::scoped_ptr<T> storage_type; -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES              typedef T const& source_reference_type;              struct dummy;              typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type; @@ -323,7 +324,7 @@ namespace boost              move_dest_type get()              {                  wait(); -                return *result; +                return static_cast<move_dest_type>(*result);              }              future_state::state get_state() @@ -403,13 +404,14 @@ namespace boost              struct all_futures_lock              { -                unsigned count; +                typedef std::vector<registered_waiter>::size_type count_type; +                count_type count;                  boost::scoped_array<boost::unique_lock<boost::mutex> > locks;                  all_futures_lock(std::vector<registered_waiter>& futures):                      count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])                  { -                    for(unsigned i=0;i<count;++i) +                    for(count_type i=0;i<count;++i)                      {                          locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);                      } @@ -632,7 +634,7 @@ namespace boost          ~unique_future()          {} -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          unique_future(unique_future && other)          {              future.swap(other.future); @@ -673,7 +675,7 @@ namespace boost          {              if(!future)              { -                throw future_uninitialized(); +                boost::throw_exception(future_uninitialized());              }              return future->get(); @@ -709,7 +711,7 @@ namespace boost          {              if(!future)              { -                throw future_uninitialized(); +                boost::throw_exception(future_uninitialized());              }              future->wait(false);          } @@ -724,7 +726,7 @@ namespace boost          {              if(!future)              { -                throw future_uninitialized(); +                boost::throw_exception(future_uninitialized());              }              return future->timed_wait_until(abs_time);          } @@ -767,7 +769,7 @@ namespace boost              future=other.future;              return *this;          } -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          shared_future(shared_future && other)          {              future.swap(other.future); @@ -830,7 +832,7 @@ namespace boost          {              if(!future)              { -                throw future_uninitialized(); +                boost::throw_exception(future_uninitialized());              }              return future->get(); @@ -866,7 +868,7 @@ namespace boost          {              if(!future)              { -                throw future_uninitialized(); +                boost::throw_exception(future_uninitialized());              }              future->wait(false);          } @@ -881,7 +883,7 @@ namespace boost          {              if(!future)              { -                throw future_uninitialized(); +                boost::throw_exception(future_uninitialized());              }              return future->timed_wait_until(abs_time);          } @@ -929,7 +931,7 @@ namespace boost          }          // Assignment -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          promise(promise && rhs):              future_obtained(rhs.future_obtained)          { @@ -974,7 +976,7 @@ namespace boost              lazy_init();              if(future_obtained)              { -                throw future_already_retrieved(); +                boost::throw_exception(future_already_retrieved());              }              future_obtained=true;              return unique_future<R>(future); @@ -986,7 +988,7 @@ namespace boost              boost::lock_guard<boost::mutex> lock(future->mutex);              if(future->done)              { -                throw promise_already_satisfied(); +                boost::throw_exception(promise_already_satisfied());              }              future->mark_finished_with_result_internal(r);          } @@ -998,7 +1000,7 @@ namespace boost              boost::lock_guard<boost::mutex> lock(future->mutex);              if(future->done)              { -                throw promise_already_satisfied(); +                boost::throw_exception(promise_already_satisfied());              }              future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));          } @@ -1009,7 +1011,7 @@ namespace boost              boost::lock_guard<boost::mutex> lock(future->mutex);              if(future->done)              { -                throw promise_already_satisfied(); +                boost::throw_exception(promise_already_satisfied());              }              future->mark_exceptional_finish_internal(p);          } @@ -1063,7 +1065,7 @@ namespace boost          }          // Assignment -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          promise(promise && rhs):              future_obtained(rhs.future_obtained)          { @@ -1109,7 +1111,7 @@ namespace boost              if(future_obtained)              { -                throw future_already_retrieved(); +                boost::throw_exception(future_already_retrieved());              }              future_obtained=true;              return unique_future<void>(future); @@ -1121,7 +1123,7 @@ namespace boost              boost::lock_guard<boost::mutex> lock(future->mutex);              if(future->done)              { -                throw promise_already_satisfied(); +                boost::throw_exception(promise_already_satisfied());              }              future->mark_finished_with_result_internal();          } @@ -1132,7 +1134,7 @@ namespace boost              boost::lock_guard<boost::mutex> lock(future->mutex);              if(future->done)              { -                throw promise_already_satisfied(); +                boost::throw_exception(promise_already_satisfied());              }              future->mark_exceptional_finish_internal(p);          } @@ -1164,7 +1166,7 @@ namespace boost                      boost::lock_guard<boost::mutex> lk(this->mutex);                      if(started)                      { -                        throw task_already_started(); +                        boost::throw_exception(task_already_started());                      }                      started=true;                  } @@ -1283,7 +1285,7 @@ namespace boost          }          // assignment -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          packaged_task(packaged_task&& other):              future_obtained(other.future_obtained)          { @@ -1326,7 +1328,7 @@ namespace boost          {              if(!task)              { -                throw task_moved(); +                boost::throw_exception(task_moved());              }              else if(!future_obtained)              { @@ -1335,7 +1337,7 @@ namespace boost              }              else              { -                throw future_already_retrieved(); +                boost::throw_exception(future_already_retrieved());              }          } @@ -1345,7 +1347,7 @@ namespace boost          {              if(!task)              { -                throw task_moved(); +                boost::throw_exception(task_moved());              }              task->run();          } diff --git a/3rdParty/Boost/src/boost/thread/locks.hpp b/3rdParty/Boost/src/boost/thread/locks.hpp index 82394a5..3cd6f28 100644 --- a/3rdParty/Boost/src/boost/thread/locks.hpp +++ b/3rdParty/Boost/src/boost/thread/locks.hpp @@ -248,7 +248,7 @@ namespace boost          {              timed_lock(target_time);          } -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          unique_lock(unique_lock&& other):              m(other.m),is_locked(other.is_locked)          { @@ -321,17 +321,17 @@ namespace boost              swap(temp);              return *this;          } -        void swap(unique_lock& other) -        { -            std::swap(m,other.m); -            std::swap(is_locked,other.is_locked); -        }          void swap(detail::thread_move_t<unique_lock<Mutex> > other)          {              std::swap(m,other->m);              std::swap(is_locked,other->is_locked);          }  #endif +        void swap(unique_lock& other) +        { +            std::swap(m,other.m); +            std::swap(is_locked,other.is_locked); +        }          ~unique_lock()          { @@ -344,7 +344,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              m->lock();              is_locked=true; @@ -353,7 +353,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              is_locked=m->try_lock();              return is_locked; @@ -379,7 +379,7 @@ namespace boost          {              if(!owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              m->unlock();              is_locked=false; @@ -416,25 +416,30 @@ namespace boost          friend class upgrade_lock<Mutex>;      }; -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES      template<typename Mutex>      void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs)      {          lhs.swap(rhs);      } -#else +#endif      template<typename Mutex>      void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)      {          lhs.swap(rhs);      } -#endif -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES      template<typename Mutex>      inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul)      { -        return ul; +        return static_cast<unique_lock<Mutex>&&>(ul); +    } + +    template<typename Mutex> +    inline unique_lock<Mutex>&& move(unique_lock<Mutex>& ul) +    { +        return static_cast<unique_lock<Mutex>&&>(ul);      }  #endif @@ -535,24 +540,24 @@ namespace boost              return *this;          } -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          void swap(shared_lock&& other)          {              std::swap(m,other.m);              std::swap(is_locked,other.is_locked);          }  #else -        void swap(shared_lock& other) -        { -            std::swap(m,other.m); -            std::swap(is_locked,other.is_locked); -        }          void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other)          {              std::swap(m,other->m);              std::swap(is_locked,other->is_locked);          }  #endif +        void swap(shared_lock& other) +        { +            std::swap(m,other.m); +            std::swap(is_locked,other.is_locked); +        }          Mutex* mutex() const          { @@ -570,7 +575,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              m->lock_shared();              is_locked=true; @@ -579,7 +584,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              is_locked=m->try_lock_shared();              return is_locked; @@ -588,7 +593,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              is_locked=m->timed_lock_shared(target_time);              return is_locked; @@ -598,7 +603,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              is_locked=m->timed_lock_shared(target_time);              return is_locked; @@ -607,7 +612,7 @@ namespace boost          {              if(!owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              m->unlock_shared();              is_locked=false; @@ -629,7 +634,7 @@ namespace boost      }; -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES      template<typename Mutex>      void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs)      { @@ -733,7 +738,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              m->lock_upgrade();              is_locked=true; @@ -742,7 +747,7 @@ namespace boost          {              if(owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              is_locked=m->try_lock_upgrade();              return is_locked; @@ -751,7 +756,7 @@ namespace boost          {              if(!owns_lock())              { -                throw boost::lock_error(); +                boost::throw_exception(boost::lock_error());              }              m->unlock_upgrade();              is_locked=false; @@ -775,7 +780,7 @@ namespace boost      }; -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES      template<typename Mutex>      unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other):          m(other.m),is_locked(other.is_locked) @@ -875,7 +880,7 @@ namespace boost              try_lock_wrapper(Mutex& m_,try_to_lock_t):                  base(m_,try_to_lock)              {} -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES              try_lock_wrapper(try_lock_wrapper&& other):                  base(other.move())              {} @@ -963,7 +968,7 @@ namespace boost              }          }; -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          template<typename Mutex>          void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs)          { diff --git a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp index 8ec6ae7..8e8f5b5 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp @@ -57,13 +57,13 @@ namespace boost              int const res=pthread_mutex_init(&internal_mutex,NULL);              if(res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              int const res2=pthread_cond_init(&cond,NULL);              if(res2)              {                  BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }          }          ~condition_variable_any() @@ -87,7 +87,7 @@ namespace boost              }              if(res)              { -                throw condition_error(); +                boost::throw_exception(condition_error());              }          } @@ -117,7 +117,7 @@ namespace boost              }              if(res)              { -                throw condition_error(); +                boost::throw_exception(condition_error());              }              return true;          } diff --git a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp index 4048cdf..59908f4 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp @@ -6,6 +6,7 @@  // (C) Copyright 2007-8 Anthony Williams  #include <boost/assert.hpp> +#include <boost/throw_exception.hpp>  #include <pthread.h>  #include <boost/thread/mutex.hpp>  #include <boost/thread/locks.hpp> @@ -30,7 +31,7 @@ namespace boost              int const res=pthread_cond_init(&cond,NULL);              if(res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }          }          ~condition_variable() diff --git a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp index 51d62ae..1f7f790 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp @@ -7,6 +7,7 @@  #include <pthread.h>  #include <boost/utility.hpp> +#include <boost/throw_exception.hpp>  #include <boost/thread/exceptions.hpp>  #include <boost/thread/locks.hpp>  #include <boost/thread/thread_time.hpp> @@ -37,7 +38,7 @@ namespace boost              int const res=pthread_mutex_init(&m,NULL);              if(res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }          }          ~mutex() @@ -89,14 +90,14 @@ namespace boost              int const res=pthread_mutex_init(&m,NULL);              if(res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }  #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK              int const res2=pthread_cond_init(&cond,NULL);              if(res2)              {                  BOOST_VERIFY(!pthread_mutex_destroy(&m)); -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              is_locked=false;  #endif diff --git a/3rdParty/Boost/src/boost/thread/pthread/once.hpp b/3rdParty/Boost/src/boost/thread/pthread/once.hpp index f278a57..6321aa2 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/once.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/once.hpp @@ -10,6 +10,7 @@  //  http://www.boost.org/LICENSE_1_0.txt)  #include <boost/thread/detail/config.hpp> +#include <boost/config.hpp>  #include <pthread.h>  #include <boost/assert.hpp> @@ -58,10 +59,13 @@ namespace boost                  if(flag.epoch==uninitialized_flag)                  {                      flag.epoch=being_initialized; +#ifndef BOOST_NO_EXCEPTIONS                      try                      { +#endif                          pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);                          f(); +#ifndef BOOST_NO_EXCEPTIONS                      }                      catch(...)                      { @@ -69,6 +73,7 @@ namespace boost                          BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));                          throw;                      } +#endif                      flag.epoch=--detail::once_global_epoch;                      BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));                  } diff --git a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp index f3f7bf1..ad3b7e1 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp @@ -7,6 +7,7 @@  #include <pthread.h>  #include <boost/utility.hpp> +#include <boost/throw_exception.hpp>  #include <boost/thread/exceptions.hpp>  #include <boost/thread/locks.hpp>  #include <boost/thread/thread_time.hpp> @@ -42,18 +43,18 @@ namespace boost              int const init_attr_res=pthread_mutexattr_init(&attr);              if(init_attr_res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);              if(set_attr_res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              int const res=pthread_mutex_init(&m,&attr);              if(res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));          } @@ -111,32 +112,32 @@ namespace boost              int const init_attr_res=pthread_mutexattr_init(&attr);              if(init_attr_res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);              if(set_attr_res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              int const res=pthread_mutex_init(&m,&attr);              if(res)              {                  BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));  #else              int const res=pthread_mutex_init(&m,NULL);              if(res)              { -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              int const res2=pthread_cond_init(&cond,NULL);              if(res2)              {                  BOOST_VERIFY(!pthread_mutex_destroy(&m)); -                throw thread_resource_error(); +                boost::throw_exception(thread_resource_error());              }              is_locked=false;              count=0; diff --git a/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp b/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp index 7cc0aa0..737c298 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp @@ -17,7 +17,7 @@ namespace boost              return new T();          } -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          template<typename T,typename A1>          inline T* heap_new(A1&& a1)          { diff --git a/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp index 751bdbd..7c6797d 100644 --- a/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp @@ -61,15 +61,30 @@ namespace boost              void lock()              { -                BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); -            } -            bool timed_lock(::boost::system_time const& wait_until) -            { -                if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit)) +                if(try_lock())                  { -                    return true; +                    return;                  }                  long old_count=active_count; +                mark_waiting_and_try_lock(old_count); + +                if(old_count&lock_flag_value) +                { +                    bool lock_acquired=false; +                    void* const sem=get_event(); + +                    do +                    { +                        BOOST_VERIFY(win32::WaitForSingleObject( +                                         sem,::boost::detail::win32::infinite)==0); +                        clear_waiting_and_try_lock(old_count); +                        lock_acquired=!(old_count&lock_flag_value); +                    } +                    while(!lock_acquired); +                } +            } +            void mark_waiting_and_try_lock(long& old_count) +            {                  for(;;)                  {                      long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value); @@ -80,6 +95,33 @@ namespace boost                      }                      old_count=current;                  } +            } + +            void clear_waiting_and_try_lock(long& old_count) +            { +                old_count&=~lock_flag_value; +                old_count|=event_set_flag_value; +                for(;;) +                { +                    long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value; +                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count); +                    if(current==old_count) +                    { +                        break; +                    } +                    old_count=current; +                } +            } +             +             +            bool timed_lock(::boost::system_time const& wait_until) +            { +                if(try_lock()) +                { +                    return true; +                } +                long old_count=active_count; +                mark_waiting_and_try_lock(old_count);                  if(old_count&lock_flag_value)                  { @@ -93,18 +135,7 @@ namespace boost                              BOOST_INTERLOCKED_DECREMENT(&active_count);                              return false;                          } -                        old_count&=~lock_flag_value; -                        old_count|=event_set_flag_value; -                        for(;;) -                        { -                            long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value; -                            long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count); -                            if(current==old_count) -                            { -                                break; -                            } -                            old_count=current; -                        } +                        clear_waiting_and_try_lock(old_count);                          lock_acquired=!(old_count&lock_flag_value);                      }                      while(!lock_acquired); diff --git a/3rdParty/Boost/src/boost/thread/win32/once.hpp b/3rdParty/Boost/src/boost/thread/win32/once.hpp index a6fcc94..c25f9ab 100644 --- a/3rdParty/Boost/src/boost/thread/win32/once.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/once.hpp @@ -30,81 +30,47 @@ namespace std  namespace boost  { -    typedef long once_flag; - -#define BOOST_ONCE_INIT 0 - -    namespace detail +    struct once_flag      { -        struct win32_mutex_scoped_lock -        { -            void* const mutex_handle; -            explicit win32_mutex_scoped_lock(void* mutex_handle_): -                mutex_handle(mutex_handle_) -            { -                BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite)); -            } -            ~win32_mutex_scoped_lock() -            { -                BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0); -            } -        private: -            void operator=(win32_mutex_scoped_lock&); -        }; +        long status; +        long count; +        long throw_count; +        void* event_handle; -#ifdef BOOST_NO_ANSI_APIS -        template <class I> -        void int_to_string(I p, wchar_t* buf) +        ~once_flag()          { -            for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) +            if(count)              { -                *buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f); +                BOOST_ASSERT(count==throw_count);              } -            *buf = 0; -        } -#else -        template <class I> -        void int_to_string(I p, char* buf) -        { -            for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) +             +            void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event_handle,0); +            if(old_event)              { -                *buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f); +                ::boost::detail::win32::CloseHandle(old_event);              } -            *buf = 0;          } -#endif +    }; + +#define BOOST_ONCE_INIT {0,0,0,0} -        // create a named mutex. It doesn't really matter what this name is -        // as long as it is unique both to this process, and to the address of "flag": -        inline void* create_once_mutex(void* flag_address) +    namespace detail +    { +        inline void* allocate_event_handle(void*& handle)          { -         -#ifdef BOOST_NO_ANSI_APIS -            typedef wchar_t char_type; -            static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; -#else -            typedef char char_type; -            static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; -#endif -            unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type); -            unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1; -            unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2; -            char_type mutex_name[once_mutex_name_length]; +            void* const new_handle=::boost::detail::win32::create_anonymous_event( +                ::boost::detail::win32::manual_reset_event, +                ::boost::detail::win32::event_initially_reset); -            std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); - -            BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t)); -            detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length); -            detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); - -#ifdef BOOST_NO_ANSI_APIS -            return win32::CreateMutexW(0, 0, mutex_name); -#else -            return win32::CreateMutexA(0, 0, mutex_name); -#endif +            void* event_handle=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&handle, +                                                                          new_handle,0); +            if(event_handle) +            { +                ::boost::detail::win32::CloseHandle(new_handle); +                return event_handle; +            } +            return new_handle;          } - -              } @@ -114,18 +80,98 @@ namespace boost          // Try for a quick win: if the procedure has already been called          // just skip through:          long const function_complete_flag_value=0xc15730e2; +        long const running_value=0x7f0725e3; +        long status; +        bool counted=false; +        void* event_handle=0; +        long throw_count=0; + +        while((status=::boost::detail::interlocked_read_acquire(&flag.status)) +              !=function_complete_flag_value) +        { +            status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0); +            if(!status) +            { +                try +                { +                    if(!event_handle) +                    { +                        event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); +                    } +                    if(event_handle) +                    { +                        ::boost::detail::win32::ResetEvent(event_handle); +                    } +                    f(); +                    if(!counted) +                    { +                        BOOST_INTERLOCKED_INCREMENT(&flag.count); +                        counted=true; +                    } +                    BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value); +                    if(!event_handle &&  +                       (::boost::detail::interlocked_read_acquire(&flag.count)>1)) +                    { +                        event_handle=::boost::detail::allocate_event_handle(flag.event_handle); +                    } +                    if(event_handle) +                    { +                        ::boost::detail::win32::SetEvent(event_handle); +                    } +                    throw_count=::boost::detail::interlocked_read_acquire(&flag.throw_count); +                    break; +                } +                catch(...) +                { +                    if(counted) +                    { +                        BOOST_INTERLOCKED_INCREMENT(&flag.throw_count); +                    } +                    BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); +                    if(!event_handle) +                    { +                        event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); +                    } +                    if(event_handle) +                    { +                        ::boost::detail::win32::SetEvent(event_handle); +                    } +                    throw; +                } +            } -        if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value) +            if(!counted) +            { +                BOOST_INTERLOCKED_INCREMENT(&flag.count); +                counted=true; +                status=::boost::detail::interlocked_read_acquire(&flag.status); +                if(status==function_complete_flag_value) +                { +                    break; +                } +                event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); +                if(!event_handle) +                { +                    event_handle=::boost::detail::allocate_event_handle(flag.event_handle); +                    continue; +                } +            } +            BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( +                             event_handle,::boost::detail::win32::infinite)); +        } +        if(counted || throw_count)          { -            void* const mutex_handle(::boost::detail::create_once_mutex(&flag)); -            BOOST_ASSERT(mutex_handle); -            detail::win32::handle_manager const closer(mutex_handle); -            detail::win32_mutex_scoped_lock const lock(mutex_handle); -       -            if(flag!=function_complete_flag_value) +            if(!BOOST_INTERLOCKED_EXCHANGE_ADD(&flag.count,(counted?-1:0)-throw_count))              { -                f(); -                BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value); +                if(!event_handle) +                { +                    event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle); +                } +                if(event_handle) +                { +                    BOOST_INTERLOCKED_EXCHANGE_POINTER(&flag.event_handle,0); +                    ::boost::detail::win32::CloseHandle(event_handle); +                }              }          }      } diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp index 9f8186f..b70623a 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp @@ -8,6 +8,7 @@  #include "thread_primitives.hpp"  #include <stdexcept>  #include <boost/assert.hpp> +#include <boost/throw_exception.hpp>  #if defined( BOOST_USE_WINDOWS_H )  # include <windows.h> @@ -60,7 +61,7 @@ namespace boost              void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);              if(!heap_memory)              { -                throw std::bad_alloc(); +                boost::throw_exception(std::bad_alloc());              }              return heap_memory;          } @@ -86,7 +87,7 @@ namespace boost              }          } -#ifdef BOOST_HAS_RVALUE_REFS +#ifndef BOOST_NO_RVALUE_REFERENCES          template<typename T,typename A1>          inline T* heap_new(A1&& a1)          { diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp index 67a1bc3..2359c38 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp @@ -11,6 +11,7 @@  //  http://www.boost.org/LICENSE_1_0.txt)  #include <boost/config.hpp> +#include <boost/throw_exception.hpp>  #include <boost/assert.hpp>  #include <boost/thread/exceptions.hpp>  #include <boost/detail/interlocked.hpp> @@ -177,7 +178,7 @@ namespace boost  #endif                                  if(!res)                  { -                    throw thread_resource_error(); +                    boost::throw_exception(thread_resource_error());                  }                  return res;              } @@ -191,7 +192,7 @@ namespace boost  #endif                                 if(!res)                  { -                    throw thread_resource_error(); +                    boost::throw_exception(thread_resource_error());                  }                  return res;              } @@ -204,7 +205,7 @@ namespace boost                  bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;                  if(!success)                  { -                    throw thread_resource_error(); +                    boost::throw_exception(thread_resource_error());                  }                  return new_handle;              } diff --git a/3rdParty/Boost/src/boost/throw_exception.hpp b/3rdParty/Boost/src/boost/throw_exception.hpp index 656b8de..1d018c5 100644 --- a/3rdParty/Boost/src/boost/throw_exception.hpp +++ b/3rdParty/Boost/src/boost/throw_exception.hpp @@ -36,16 +36,32 @@  #if !defined( BOOST_EXCEPTION_DISABLE )  # include <boost/exception/exception.hpp>  # include <boost/current_function.hpp> -# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(::boost::enable_error_info(x) <<\ -    ::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\ -    ::boost::throw_file(__FILE__) <<\ -    ::boost::throw_line(__LINE__)) +# define BOOST_THROW_EXCEPTION(x) ::boost::exception_detail::throw_exception_(x,BOOST_CURRENT_FUNCTION,__FILE__,__LINE__)  #else  # define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x)  #endif  namespace boost  { +#if !defined( BOOST_EXCEPTION_DISABLE ) +    namespace +    exception_detail +    { +        template <class E> +        void +        throw_exception_( E const & x, char const * current_function, char const * file, int line ) +        { +            throw_exception( +                set_info( +                    set_info( +                        set_info( +                            enable_error_info(x), +                            throw_function(current_function)), +                        throw_file(file)), +                    throw_line(line))); +        } +    } +#endif  #ifdef BOOST_NO_EXCEPTIONS diff --git a/3rdParty/Boost/src/boost/timer.hpp b/3rdParty/Boost/src/boost/timer.hpp deleted file mode 100644 index 1e3571e..0000000 --- a/3rdParty/Boost/src/boost/timer.hpp +++ /dev/null @@ -1,72 +0,0 @@ -//  boost timer.hpp header file  ---------------------------------------------// - -//  Copyright Beman Dawes 1994-99.  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) - -//  See http://www.boost.org/libs/timer for documentation. - -//  Revision History -//  01 Apr 01  Modified to use new <boost/limits.hpp> header. (JMaddock) -//  12 Jan 01  Change to inline implementation to allow use without library -//             builds. See docs for more rationale. (Beman Dawes)  -//  25 Sep 99  elapsed_max() and elapsed_min() added (John Maddock) -//  16 Jul 99  Second beta -//   6 Jul 99  Initial boost version - -#ifndef BOOST_TIMER_HPP -#define BOOST_TIMER_HPP - -#include <boost/config.hpp> -#include <ctime> -#include <boost/limits.hpp> - -# ifdef BOOST_NO_STDC_NAMESPACE -    namespace std { using ::clock_t; using ::clock; } -# endif - - -namespace boost { - -//  timer  -------------------------------------------------------------------// - -//  A timer object measures elapsed time. - -//  It is recommended that implementations measure wall clock rather than CPU -//  time since the intended use is performance measurement on systems where -//  total elapsed time is more important than just process or CPU time. - -//  Warnings: The maximum measurable elapsed time may well be only 596.5+ hours -//  due to implementation limitations.  The accuracy of timings depends on the -//  accuracy of timing information provided by the underlying platform, and -//  this varies a great deal from platform to platform. - -class timer -{ - public: -         timer() { _start_time = std::clock(); } // postcondition: elapsed()==0 -//         timer( const timer& src );      // post: elapsed()==src.elapsed() -//        ~timer(){} -//  timer& operator=( const timer& src );  // post: elapsed()==src.elapsed() -  void   restart() { _start_time = std::clock(); } // post: elapsed()==0 -  double elapsed() const                  // return elapsed time in seconds -    { return  double(std::clock() - _start_time) / CLOCKS_PER_SEC; } - -  double elapsed_max() const   // return estimated maximum value for elapsed() -  // Portability warning: elapsed_max() may return too high a value on systems -  // where std::clock_t overflows or resets at surprising values. -  { -    return (double((std::numeric_limits<std::clock_t>::max)()) -       - double(_start_time)) / double(CLOCKS_PER_SEC);  -  } - -  double elapsed_min() const            // return minimum value for elapsed() -   { return double(1)/double(CLOCKS_PER_SEC); } - - private: -  std::clock_t _start_time; -}; // timer - -} // namespace boost - -#endif  // BOOST_TIMER_HPP diff --git a/3rdParty/Boost/src/boost/type_traits/cv_traits.hpp b/3rdParty/Boost/src/boost/type_traits/cv_traits.hpp deleted file mode 100644 index 5bd6c4f..0000000 --- a/3rdParty/Boost/src/boost/type_traits/cv_traits.hpp +++ /dev/null @@ -1,24 +0,0 @@ -//  (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard -//  Hinnant & John Maddock 2000.   -//  Use, modification and distribution are subject to 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). -// -//  See http://www.boost.org/libs/type_traits for most recent version including documentation. -// -//  defines traits classes for cv-qualified types: -//  is_const, is_volatile, remove_const, remove_volatile, remove_cv. - -#ifndef BOOST_TT_CV_TRAITS_HPP_INCLUDED -#define BOOST_TT_CV_TRAITS_HPP_INCLUDED - -#include <boost/type_traits/add_const.hpp> -#include <boost/type_traits/add_volatile.hpp> -#include <boost/type_traits/add_cv.hpp> -#include <boost/type_traits/is_const.hpp> -#include <boost/type_traits/is_volatile.hpp> -#include <boost/type_traits/remove_const.hpp> -#include <boost/type_traits/remove_volatile.hpp> -#include <boost/type_traits/remove_cv.hpp> - -#endif // BOOST_TT_CV_TRAITS_HPP_INCLUDED diff --git a/3rdParty/Boost/src/boost/type_traits/is_empty.hpp b/3rdParty/Boost/src/boost/type_traits/is_empty.hpp index c8eb791..45c4e9e 100644 --- a/3rdParty/Boost/src/boost/type_traits/is_empty.hpp +++ b/3rdParty/Boost/src/boost/type_traits/is_empty.hpp @@ -36,6 +36,12 @@ namespace boost {  namespace detail {  #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4624) // destructor could not be generated +#endif +  template <typename T>  struct empty_helper_t1 : public T  { @@ -47,6 +53,10 @@ private:     empty_helper_t1& operator=(const empty_helper_t1&);  }; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +  struct empty_helper_t2 { int i[256]; };  #if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) diff --git a/3rdParty/Boost/src/boost/units/detail/utility.hpp b/3rdParty/Boost/src/boost/units/detail/utility.hpp new file mode 100644 index 0000000..da46b45 --- /dev/null +++ b/3rdParty/Boost/src/boost/units/detail/utility.hpp @@ -0,0 +1,104 @@ +// Boost.Units - A C++ library for zero-overhead dimensional analysis and  +// unit/quantity manipulation and conversion +// +// Copyright (C) 2003-2008 Matthias Christian Schabel +// Copyright (C) 2008 Steven Watanabe +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_UNITS_UTILITY_HPP +#define BOOST_UNITS_UTILITY_HPP + +#include <cstdlib> +#include <typeinfo> +#include <string> + +#if defined(__GLIBCXX__) || defined(__GLIBCPP__) +#define BOOST_UNITS_USE_DEMANGLING +#include <cxxabi.h> +#endif // __GNUC__ + +#ifdef BOOST_UNITS_USE_DEMANGLING + +#include <boost/algorithm/string/replace.hpp> + +namespace boost { + +namespace units { + +namespace detail { + +inline +std::string +demangle(const char* name) +{ +    // need to demangle C++ symbols +    char*       realname; +    std::size_t len;  +    int         stat; +      +    realname = abi::__cxa_demangle(name,NULL,&len,&stat); +     +    if (realname != NULL) +    { +        std::string   out(realname); +         +        std::free(realname); +         +        boost::replace_all(out,"boost::units::",""); +         +        return out; +    } +     +    return std::string("demangle :: error - unable to demangle specified symbol"); +} + +} // namespace detail + +template<class L> +std::string simplify_typename(const L& /*source*/) +{ +    const std::string   demangled = detail::demangle(typeid(L).name()); + +    return demangled; +} + +} // namespace units + +} // namespace boost + +#else // BOOST_UNITS_USE_DEMANGLING + +namespace boost { + +namespace units { + +namespace detail { + +inline +std::string +demangle(const char* name) +{ +    return name; +} + +} // namespace detail + +template<class L> +std::string simplify_typename(const L& /*source*/) +{ +    return std::string(typeid(L).name()); +} + +} // namespace units + +} // namespace boost + +// To get system-specific predefined macros: +// gcc -arch ppc -dM -E - < /dev/null | sort  + +#endif // BOOST_UNITS_USE_DEMANGLING + +#endif // BOOST_UNITS_UTILITY_HPP diff --git a/3rdParty/Boost/src/boost/utility/value_init.hpp b/3rdParty/Boost/src/boost/utility/value_init.hpp deleted file mode 100644 index 5aefac9..0000000 --- a/3rdParty/Boost/src/boost/utility/value_init.hpp +++ /dev/null @@ -1,151 +0,0 @@ -// (C) Copyright 2002-2008, Fernando Luis Cacciola Carballal. -// -// 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) -// -// 21 Ago 2002 (Created) Fernando Cacciola -// 24 Dec 2007 (Refactored and worked around various compiler bugs) Fernando Cacciola, Niels Dekker -// 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola -// 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola -// 20 Feb 2009 (Fixed logical const-ness issues) Niels Dekker, Fernando Cacciola -// -#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP -#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP - -// Note: The implementation of boost::value_initialized had to deal with the -// fact that various compilers haven't fully implemented value-initialization. -// The constructor of boost::value_initialized<T> works around these compiler -// issues, by clearing the bytes of T, before constructing the T object it -// contains. More details on these issues are at libs/utility/value_init.htm - -#include <boost/aligned_storage.hpp> -#include <boost/detail/workaround.hpp> -#include <boost/static_assert.hpp> -#include <boost/type_traits/cv_traits.hpp> -#include <boost/type_traits/alignment_of.hpp> -#include <boost/swap.hpp> -#include <cstring> -#include <new> - -namespace boost { - -template<class T> -class value_initialized -{ -  private : -    struct wrapper -    { -#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) -      typename -#endif  -      remove_const<T>::type data; -    }; - -    mutable -#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) -      typename -#endif  -      aligned_storage<sizeof(wrapper), alignment_of<wrapper>::value>::type x; - -    wrapper * wrapper_address() const -    { -      return static_cast<wrapper *>( static_cast<void*>(&x)); -    } - -  public : - -    value_initialized() -    { -      std::memset(&x, 0, sizeof(x)); -#ifdef BOOST_MSVC -#pragma warning(push) -#if _MSC_VER >= 1310 -// When using MSVC 7.1 or higher, the following placement new expression may trigger warning C4345: -// "behavior change: an object of POD type constructed with an initializer of the form () -// will be default-initialized".  It is safe to ignore this warning when using value_initialized. -#pragma warning(disable: 4345) -#endif -#endif -      new (wrapper_address()) wrapper(); -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif -    } - -    value_initialized(value_initialized const & arg) -    { -      new (wrapper_address()) wrapper( static_cast<wrapper const &>(*(arg.wrapper_address()))); -    } - -    value_initialized & operator=(value_initialized const & arg) -    { -      // Assignment is only allowed when T is non-const. -      BOOST_STATIC_ASSERT( ! is_const<T>::value ); -      *wrapper_address() = static_cast<wrapper const &>(*(arg.wrapper_address())); -      return *this; -    } - -    ~value_initialized() -    { -      wrapper_address()->wrapper::~wrapper(); -    } - -    T const & data() const -    { -      return wrapper_address()->data; -    } - -    T& data() -    { -      return wrapper_address()->data; -    } - -    void swap(value_initialized & arg) -    { -      ::boost::swap( this->data(), arg.data() ); -    } - -    operator T const &() const { return this->data(); } - -    operator T&() { return this->data(); } - -} ; - - - -template<class T> -T const& get ( value_initialized<T> const& x ) -{ -  return x.data() ; -} -template<class T> -T& get ( value_initialized<T>& x ) -{ -  return x.data() ; -} - -template<class T> -void swap ( value_initialized<T> & lhs, value_initialized<T> & rhs ) -{ -  lhs.swap(rhs) ; -} - - -class initialized_value_t -{ -  public : -     -    template <class T> operator T() const -    { -      return get( value_initialized<T>() ); -    } -}; - -initialized_value_t const initialized_value = {} ; - - -} // namespace boost - - -#endif diff --git a/3rdParty/Boost/src/boost/version.hpp b/3rdParty/Boost/src/boost/version.hpp index e95ff85..82a1daf 100644 --- a/3rdParty/Boost/src/boost/version.hpp +++ b/3rdParty/Boost/src/boost/version.hpp @@ -19,7 +19,7 @@  //  BOOST_VERSION / 100 % 1000 is the minor version  //  BOOST_VERSION / 100000 is the major version -#define BOOST_VERSION 104200 +#define BOOST_VERSION 104300  //  //  BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION @@ -27,7 +27,7 @@  //  number, y is the minor version number, and z is the patch level if not 0.  //  This is used by <config/auto_link.hpp> to select which library version to link to. -#define BOOST_LIB_VERSION "1_42" +#define BOOST_LIB_VERSION "1_43"  #endif diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp index 3a5ce7c..1c13a9a 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp +++ b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp @@ -13,6 +13,7 @@  #include <boost/thread/locks.hpp>  #include <boost/thread/once.hpp>  #include <boost/thread/tss.hpp> +#include <boost/throw_exception.hpp>  #ifdef __linux__  #include <sys/sysinfo.h>  #elif defined(__APPLE__) || defined(__FreeBSD__) @@ -186,7 +187,7 @@ namespace boost          if (res != 0)          {              thread_info->self.reset(); -            throw thread_resource_error(); +            boost::throw_exception(thread_resource_error());          }      } diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl b/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl index 5ec3b17..b75a135 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl +++ b/3rdParty/Boost/src/libs/thread/src/pthread/timeconv.inl @@ -1,11 +1,14 @@  // Copyright (C) 2001-2003  // William E. Kempf +// Copyright (C) 2009 Anthony Williams  //  //  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)  // boostinspect:nounnamed +#include <boost/assert.hpp> +  namespace {  const int MILLISECONDS_PER_SECOND = 1000;  const int NANOSECONDS_PER_SECOND = 1000000000; @@ -18,7 +21,7 @@ inline void to_time(int milliseconds, boost::xtime& xt)  {      int res = 0;      res = boost::xtime_get(&xt, boost::TIME_UTC); -    assert(res == boost::TIME_UTC); +    BOOST_ASSERT(res == boost::TIME_UTC);      xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);      xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * @@ -55,7 +58,7 @@ inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)      boost::xtime cur;      int res = 0;      res = boost::xtime_get(&cur, boost::TIME_UTC); -    assert(res == boost::TIME_UTC); +    BOOST_ASSERT(res == boost::TIME_UTC);      if (boost::xtime_cmp(xt, cur) <= 0)      { @@ -86,7 +89,7 @@ inline void to_duration(boost::xtime xt, int& milliseconds)      boost::xtime cur;      int res = 0;      res = boost::xtime_get(&cur, boost::TIME_UTC); -    assert(res == boost::TIME_UTC); +    BOOST_ASSERT(res == boost::TIME_UTC);      if (boost::xtime_cmp(xt, cur) <= 0)          milliseconds = 0; @@ -108,7 +111,7 @@ inline void to_microduration(boost::xtime xt, int& microseconds)      boost::xtime cur;      int res = 0;      res = boost::xtime_get(&cur, boost::TIME_UTC); -    assert(res == boost::TIME_UTC); +    BOOST_ASSERT(res == boost::TIME_UTC);      if (boost::xtime_cmp(xt, cur) <= 0)          microseconds = 0; diff --git a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp index 46af860..b85e650 100644 --- a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp +++ b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp @@ -17,6 +17,7 @@  #include <boost/thread/once.hpp>  #include <boost/thread/tss.hpp>  #include <boost/assert.hpp> +#include <boost/throw_exception.hpp>  #include <boost/thread/detail/tss_hooks.hpp>  #include <boost/date_time/posix_time/conversion.hpp> @@ -188,7 +189,7 @@ namespace boost          uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);          if(!new_thread)          { -            throw thread_resource_error(); +            boost::throw_exception(thread_resource_error());          }          intrusive_ptr_add_ref(thread_info.get());          thread_info->thread_handle=(detail::win32::handle)(new_thread); diff --git a/3rdParty/Boost/update.sh b/3rdParty/Boost/update.sh index 1ef3aa5..bb5715c 100755 --- a/3rdParty/Boost/update.sh +++ b/3rdParty/Boost/update.sh @@ -5,6 +5,10 @@ fi  TARGET_DIR=src +if [ ! -d "$TARGET_DIR" ]; then +	mkdir $TARGET_DIR +fi +  ./bcp --boost="$1" \  	tools/bcp \  	bind.hpp \ @@ -20,6 +24,7 @@ TARGET_DIR=src  	program_options.hpp \  	thread.hpp \  	asio.hpp \ +	uuid.hpp \  	regex.hpp \  	$TARGET_DIR @@ -30,4 +35,4 @@ LIBS="date_time regex system thread signals filesystem program_options"  for lib in $LIBS; do  	rm -rf $TARGET_DIR/libs/$lib/build $TARGET_DIR/libs/$lib/*.doc $TARGET_DIR/libs/$lib/src/*.doc $TARGET_DIR/libs/$lib/src/CMakeLists.txt $TARGET_DIR/libs/$lib/test  done -rm -rf $TARGET_DIR/tools/bcp/*.html $TARGET_DIR/libs/test $TARGET_DIR/doc $TARGET_DIR/boost.png $TARGET_DIR/boost/test $TARGET_DIR/tools/bcp/Jamfile.v2 $TARGET_DIR/tools/bcp/doc $TARGET_DIR/tools/bcp/test +rm -rf $TARGET_DIR/tools/bcp/*.html $TARGET_DIR/libs/test $TARGET_DIR/doc $TARGET_DIR/boost.png $TARGET_DIR/boost/test $TARGET_DIR/tools/bcp/Jamfile.v2 $TARGET_DIR/tools/bcp/doc $TARGET_DIR/tools/bcp/test $TARGET_DIR/Jamroot diff --git a/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml b/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml index f980fce..e0a63ae 100644 --- a/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml +++ b/Documentation/SwiftenDevelopersGuide/Swiften Developers Guide.xml @@ -19,4 +19,31 @@        </para>      </sect1>    </chapter> + +  <chapter> +    <title>Tutorial: Writing an Echo Bot</title> +     +    <para> +      In this chapter, we build a simple echo bot, illustrating how +      to use and extend Swiften for your own purposes. +    </para> + +    <sect1> +      <title>Setting up the build environment</title> +      <para> +      </para> +    </sect1> + +    <sect1> +      <title>Connecting to the network</title> +      <para> +      </para> +    </sect1> + +    <sect1> +      <title>T</title> +      <para> +      </para> +    </sect1> +  </chapter>  </book>  | 
 Swift