summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost')
-rw-r--r--3rdParty/Boost/src/boost/array.hpp29
-rw-r--r--3rdParty/Boost/src/boost/asio/basic_socket_streambuf.hpp8
-rw-r--r--3rdParty/Boost/src/boost/asio/buffers_iterator.hpp138
-rw-r--r--3rdParty/Boost/src/boost/asio/datagram_socket_service.hpp29
-rw-r--r--3rdParty/Boost/src/boost/asio/deadline_timer_service.hpp36
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/base_from_completion_cond.hpp67
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/buffer_sequence_adapter.hpp254
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/completion_handler.hpp73
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/consuming_buffers.hpp54
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/deadline_timer_service.hpp63
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor.hpp412
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/dev_poll_reactor_fwd.hpp1
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/epoll_reactor.hpp747
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/epoll_reactor_fwd.hpp1
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/event.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/fenced_block.hpp72
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/gcc_fenced_block.hpp65
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/gcc_x86_fenced_block.hpp63
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/handler_base_from_member.hpp78
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/handler_queue.hpp231
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/hash_map.hpp93
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/indirect_handler_queue.hpp293
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/kqueue_reactor.hpp710
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/kqueue_reactor_fwd.hpp1
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/macos_fenced_block.hpp59
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/mutex.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/null_buffers_op.hpp79
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/null_event.hpp10
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/null_fenced_block.hpp45
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/null_mutex.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/null_signal_blocker.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/null_thread.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/null_tss_ptr.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/op_queue.hpp158
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/operation.hpp45
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/posix_event.hpp10
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/posix_mutex.hpp22
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/reactive_descriptor_service.hpp510
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/reactive_serial_port_service.hpp23
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/reactive_socket_service.hpp1195
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/reactor.hpp34
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/reactor_fwd.hpp48
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/reactor_op.hpp62
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp383
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/resolver_service.hpp247
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/select_reactor.hpp447
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/service_registry.hpp175
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/signal_blocker.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/socket_types.hpp8
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/solaris_fenced_block.hpp59
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/strand_service.hpp445
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/task_io_service.hpp287
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/task_io_service_2lock.hpp475
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/task_io_service_operation.hpp71
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/thread.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/timer_op.hpp46
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/timer_queue.hpp334
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/timer_queue_base.hpp32
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/timer_queue_fwd.hpp33
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/timer_queue_set.hpp117
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/timer_scheduler.hpp36
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/timer_scheduler_fwd.hpp48
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/tss_ptr.hpp6
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_event.hpp9
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_fenced_block.hpp77
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_iocp_handle_service.hpp429
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_iocp_io_service.hpp545
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_iocp_operation.hpp91
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_iocp_overlapped_ptr.hpp124
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_iocp_serial_port_service.hpp10
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_iocp_socket_service.hpp1693
-rw-r--r--3rdParty/Boost/src/boost/asio/detail/win_mutex.hpp46
-rw-r--r--3rdParty/Boost/src/boost/asio/impl/io_service.ipp12
-rw-r--r--3rdParty/Boost/src/boost/asio/impl/read.ipp202
-rw-r--r--3rdParty/Boost/src/boost/asio/impl/read_at.ipp8
-rw-r--r--3rdParty/Boost/src/boost/asio/impl/write.ipp180
-rw-r--r--3rdParty/Boost/src/boost/asio/impl/write_at.ipp8
-rw-r--r--3rdParty/Boost/src/boost/asio/io_service.hpp47
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/address_v4.hpp2
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/address_v6.hpp2
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/basic_resolver.hpp6
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/basic_resolver_iterator.hpp76
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/basic_resolver_query.hpp115
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/icmp.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/resolver_query_base.hpp89
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/resolver_service.hpp6
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/tcp.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/ip/udp.hpp4
-rw-r--r--3rdParty/Boost/src/boost/asio/posix/stream_descriptor_service.hpp35
-rw-r--r--3rdParty/Boost/src/boost/asio/raw_socket_service.hpp29
-rw-r--r--3rdParty/Boost/src/boost/asio/read.hpp15
-rw-r--r--3rdParty/Boost/src/boost/asio/read_until.hpp93
-rw-r--r--3rdParty/Boost/src/boost/asio/serial_port_service.hpp19
-rw-r--r--3rdParty/Boost/src/boost/asio/socket_acceptor_service.hpp29
-rw-r--r--3rdParty/Boost/src/boost/asio/stream_socket_service.hpp29
-rw-r--r--3rdParty/Boost/src/boost/asio/version.hpp2
-rw-r--r--3rdParty/Boost/src/boost/asio/windows/random_access_handle_service.hpp7
-rw-r--r--3rdParty/Boost/src/boost/asio/windows/stream_handle_service.hpp7
-rw-r--r--3rdParty/Boost/src/boost/asio/write.hpp20
-rw-r--r--3rdParty/Boost/src/boost/concept/detail/has_constraints.hpp2
-rw-r--r--3rdParty/Boost/src/boost/concept_check.hpp11
-rw-r--r--3rdParty/Boost/src/boost/config/compiler/gcc.hpp6
-rw-r--r--3rdParty/Boost/src/boost/config/compiler/nvcc.hpp85
-rw-r--r--3rdParty/Boost/src/boost/config/compiler/pgi.hpp21
-rw-r--r--3rdParty/Boost/src/boost/config/compiler/visualc.hpp2
-rw-r--r--3rdParty/Boost/src/boost/config/platform/symbian.hpp94
-rw-r--r--3rdParty/Boost/src/boost/config/select_compiler_config.hpp5
-rw-r--r--3rdParty/Boost/src/boost/config/select_platform_config.hpp4
-rw-r--r--3rdParty/Boost/src/boost/config/suffix.hpp9
-rw-r--r--3rdParty/Boost/src/boost/cstdlib.hpp41
-rw-r--r--3rdParty/Boost/src/boost/date_time/gregorian/conversion.hpp4
-rw-r--r--3rdParty/Boost/src/boost/date_time/posix_time/conversion.hpp4
-rw-r--r--3rdParty/Boost/src/boost/detail/binary_search.hpp216
-rw-r--r--3rdParty/Boost/src/boost/detail/container_fwd.hpp4
-rw-r--r--3rdParty/Boost/src/boost/detail/lcast_precision.hpp4
-rw-r--r--3rdParty/Boost/src/boost/detail/scoped_enum_emulation.hpp4
-rw-r--r--3rdParty/Boost/src/boost/exception/detail/error_info_impl.hpp6
-rw-r--r--3rdParty/Boost/src/boost/exception/detail/exception_ptr.hpp209
-rw-r--r--3rdParty/Boost/src/boost/exception/detail/is_output_streamable.hpp17
-rw-r--r--3rdParty/Boost/src/boost/exception/detail/type_info.hpp14
-rw-r--r--3rdParty/Boost/src/boost/exception/diagnostic_information.hpp8
-rw-r--r--3rdParty/Boost/src/boost/exception/exception.hpp98
-rw-r--r--3rdParty/Boost/src/boost/exception/info.hpp48
-rw-r--r--3rdParty/Boost/src/boost/functional/hash/detail/hash_float_generic.hpp8
-rw-r--r--3rdParty/Boost/src/boost/functional/hash/hash.hpp6
-rw-r--r--3rdParty/Boost/src/boost/iterator/iterator_concepts.hpp284
-rw-r--r--3rdParty/Boost/src/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp8
-rw-r--r--3rdParty/Boost/src/boost/mpl/aux_/template_arity.hpp8
-rw-r--r--3rdParty/Boost/src/boost/mpl/aux_/unwrap.hpp47
-rw-r--r--3rdParty/Boost/src/boost/mpl/for_each.hpp116
-rw-r--r--3rdParty/Boost/src/boost/mpl/is_sequence.hpp112
-rw-r--r--3rdParty/Boost/src/boost/preprocessor/seq/for_each.hpp60
-rw-r--r--3rdParty/Boost/src/boost/progress.hpp143
-rwxr-xr-x3rdParty/Boost/src/boost/range/algorithm/equal.hpp188
-rw-r--r--3rdParty/Boost/src/boost/range/as_literal.hpp30
-rw-r--r--3rdParty/Boost/src/boost/range/concepts.hpp331
-rw-r--r--3rdParty/Boost/src/boost/range/const_iterator.hpp11
-rwxr-xr-x3rdParty/Boost/src/boost/range/detail/extract_optional_type.hpp52
-rw-r--r--3rdParty/Boost/src/boost/range/detail/implementation_help.hpp14
-rwxr-xr-x3rdParty/Boost/src/boost/range/detail/misc_concept.hpp33
-rw-r--r--3rdParty/Boost/src/boost/range/iterator.hpp64
-rw-r--r--3rdParty/Boost/src/boost/range/iterator_range.hpp659
-rwxr-xr-x3rdParty/Boost/src/boost/range/iterator_range_core.hpp542
-rwxr-xr-x3rdParty/Boost/src/boost/range/iterator_range_io.hpp93
-rw-r--r--3rdParty/Boost/src/boost/range/mutable_iterator.hpp11
-rw-r--r--3rdParty/Boost/src/boost/range/size.hpp2
-rw-r--r--3rdParty/Boost/src/boost/range/size_type.hpp3
-rw-r--r--3rdParty/Boost/src/boost/smart_ptr/detail/sp_convertible.hpp2
-rw-r--r--3rdParty/Boost/src/boost/thread/barrier.hpp3
-rw-r--r--3rdParty/Boost/src/boost/thread/detail/thread.hpp36
-rw-r--r--3rdParty/Boost/src/boost/thread/future.hpp56
-rw-r--r--3rdParty/Boost/src/boost/thread/locks.hpp69
-rw-r--r--3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp8
-rw-r--r--3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp3
-rw-r--r--3rdParty/Boost/src/boost/thread/pthread/mutex.hpp7
-rw-r--r--3rdParty/Boost/src/boost/thread/pthread/once.hpp5
-rw-r--r--3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp17
-rw-r--r--3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp2
-rw-r--r--3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp67
-rw-r--r--3rdParty/Boost/src/boost/thread/win32/once.hpp190
-rw-r--r--3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp5
-rw-r--r--3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp7
-rw-r--r--3rdParty/Boost/src/boost/throw_exception.hpp24
-rw-r--r--3rdParty/Boost/src/boost/timer.hpp72
-rw-r--r--3rdParty/Boost/src/boost/type_traits/cv_traits.hpp24
-rw-r--r--3rdParty/Boost/src/boost/type_traits/is_empty.hpp10
-rw-r--r--3rdParty/Boost/src/boost/units/detail/utility.hpp104
-rw-r--r--3rdParty/Boost/src/boost/utility/value_init.hpp151
-rw-r--r--3rdParty/Boost/src/boost/version.hpp4
169 files changed, 8627 insertions, 9153 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