diff --git a/Subtrees/beast/Builds/VisualStudio2012/Beast.props b/Subtrees/beast/Builds/VisualStudio2012/Beast.props
index f6d2951a8e..2428672bea 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/Beast.props
+++ b/Subtrees/beast/Builds/VisualStudio2012/Beast.props
@@ -9,6 +9,7 @@
_CRTDBG_MAP_ALLOC;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
true
false
+ %(AdditionalIncludeDirectories)
diff --git a/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h b/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h
index db09b0f7be..b21ea0df16 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h
+++ b/Subtrees/beast/Builds/VisualStudio2012/BeastConfig.h
@@ -142,4 +142,16 @@
#define BEAST_DISABLE_CONTRACT_CHECKS 0
#endif
+//------------------------------------------------------------------------------
+
+/** Config: BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
+
+ Setting this option makes Socket-derived classes generate compile errors if
+ they forget any of the virtual overrides As some Socket-derived classes
+ intentionally omit member functions that are not applicable, this macro
+ should only be enabled temporarily when writing your own Socket-derived class,
+ to make sure that the function signatures match as expected.
+*/
+#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 0
+
#endif
diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
index 0df23244e3..fd50844f96 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
+++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
@@ -69,7 +69,11 @@
-
+
+
+
+
+
@@ -78,13 +82,13 @@
-
+
+
-
@@ -303,7 +307,7 @@
-
+
true
true
true
@@ -340,6 +344,12 @@
true
true
+
+ true
+ true
+ true
+ true
+
true
true
@@ -361,6 +371,8 @@
true
true
+ true
+ true
true
diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
index 440982c122..3218fb0428 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -155,12 +155,12 @@
{ccdc0c8e-f77a-486e-ba2f-29c10ec97f18}
-
- {dfa79046-33ef-4653-a6f9-83954b76a10f}
-
{4856837a-fa72-4252-8e8f-a112c1dbb3d2}
+
+ {beb81776-4aad-401d-8826-81478dbbf30b}
+
@@ -824,9 +824,6 @@
beast_core\memory
-
- beast_asio\streams
-
beast_asio\handshake
@@ -839,24 +836,39 @@
beast_asio\handshake
-
- beast_asio\handshake
-
beast_asio\handshake
-
- beast_asio\basics
-
beast_core\memory
-
- beast_asio\sockets
-
beast_asio\system
+
+ beast_asio\handshake
+
+
+ beast_asio\handshake
+
+
+ beast_asio\async
+
+
+ beast_asio\async
+
+
+ beast_asio\async
+
+
+ beast_asio\async
+
+
+ beast_asio\async
+
+
+ beast_asio\handshake
+
@@ -1318,8 +1330,11 @@
beast_asio\handshake
-
- beast_asio\basics
+
+ beast_asio\system
+
+
+ beast_asio\async
diff --git a/Subtrees/beast/modules/beast_asio/async/beast_ComposedAsyncOperation.h b/Subtrees/beast/modules/beast_asio/async/beast_ComposedAsyncOperation.h
new file mode 100644
index 0000000000..ca109ebd96
--- /dev/null
+++ b/Subtrees/beast/modules/beast_asio/async/beast_ComposedAsyncOperation.h
@@ -0,0 +1,100 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_COMPOSEDASYNCOPERATION_H_INCLUDED
+#define BEAST_COMPOSEDASYNCOPERATION_H_INCLUDED
+
+/** Base class for creating composed asynchronous operations.
+ The composed operation will have its operator() overloads called with
+ the same context and execution safety guarantees as the original
+ SharedHandler.
+*/
+class ComposedAsyncOperation : public SharedHandler
+{
+protected:
+ /** Construct the composed operation.
+ The composed operation will execute in the context of the
+ SharedHandler. A reference to the SharedHandler is maintained
+ for the lifetime of the composed operation.
+ */
+ ComposedAsyncOperation (std::size_t size, SharedHandlerPtr const& ptr)
+ : m_size (size)
+ , m_ptr (ptr)
+ {
+ // Illegal to do anything with handler here, because
+ // usually it hasn't been assigned by the derived class yet.
+ }
+
+ ~ComposedAsyncOperation ()
+ {
+ }
+
+ void invoke (invoked_type& invoked)
+ {
+ boost_asio_handler_invoke_helpers::
+ invoke (invoked, *m_ptr);
+ }
+
+ void* allocate (std::size_t size)
+ {
+ return boost_asio_handler_alloc_helpers::
+ allocate (size, *m_ptr);
+ }
+
+ void deallocate (void* p, std::size_t size)
+ {
+ boost_asio_handler_alloc_helpers::
+ deallocate (p, size, *m_ptr);
+ }
+
+ /** Override this function as needed.
+ Usually you will logical-and your own continuation condition. In
+ the following example, isContinuing is a derived class member:
+
+ @code
+
+ bool derived::is_continuation ()
+ {
+ bool const ourResult = this->isContinuing ()
+ return ourResult || ComposedAsyncOperation ::is_contiation ();
+ }
+
+ @endcode
+ */
+ bool is_continuation ()
+ {
+#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
+ return boost_asio_handler_cont_helpers::
+ is_continuation (*m_ptr);
+#else
+ return false;
+#endif
+ }
+
+ void destroy ()
+ {
+ delete this;
+ }
+
+private:
+ std::size_t const m_size;
+ SharedHandlerPtr const m_ptr;
+};
+
+#endif
diff --git a/Subtrees/beast/modules/beast_asio/async/beast_SharedHandler.cpp b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandler.cpp
new file mode 100644
index 0000000000..cf4cea5ca7
--- /dev/null
+++ b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandler.cpp
@@ -0,0 +1,47 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+void SharedHandler::operator() ()
+{
+ pure_virtual_called (__FILE__, __LINE__);
+}
+
+void SharedHandler::operator() (error_code const&)
+{
+ pure_virtual_called (__FILE__, __LINE__);
+}
+
+void SharedHandler::operator() (error_code const&, std::size_t)
+{
+ pure_virtual_called (__FILE__, __LINE__);
+}
+
+void SharedHandler::pure_virtual_called (char const* fileName, int lineNumber)
+{
+ // These shouldn't be getting called. But since the object returned
+ // by most implementations of bind have operator() up to high arity
+ // levels, it is not generally possible to write a traits test that
+ // works in all scenarios for detecting a particular signature of a
+ // handler.
+ //
+ // We use Throw here so beast has a chance to dump the stack BEFORE
+ // the stack is unwound.
+ //
+ Throw (std::runtime_error ("pure virtual called"), fileName, lineNumber);
+}
diff --git a/Subtrees/beast/modules/beast_asio/async/beast_SharedHandler.h b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandler.h
new file mode 100644
index 0000000000..6e2d4f2f8b
--- /dev/null
+++ b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandler.h
@@ -0,0 +1,134 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_SHAREDHANDLER_H_INCLUDED
+#define BEAST_SHAREDHANDLER_H_INCLUDED
+
+template
+struct SharedHandlerAllocator;
+
+/** Reference counted wrapper that can hold any other boost::asio handler.
+
+ This object will match these signatures:
+
+ @code
+
+ void (void)
+ void (system::error_code)
+ void (system::error_code, std::size_t)
+
+ @endcode
+
+ If the underlying implementation does not support the signature,
+ undefined behavior will result.
+
+ Supports these concepts:
+ Destructible
+*/
+class SharedHandler : public SharedObject
+{
+protected:
+ typedef boost::system::error_code error_code;
+ typedef boost::function invoked_type;
+
+ SharedHandler () noexcept { }
+
+public:
+ // For asio::async_result<>
+ typedef void result_type;
+
+ typedef SharedObjectPtr Ptr;
+
+ virtual void operator() ();
+ virtual void operator() (error_code const&);
+ virtual void operator() (error_code const&, std::size_t);
+
+ /** Dispatch the Function on our context. */
+ /*
+ template
+ void dispatch (Dispatcher& dispatcher, BOOST_ASIO_MOVE_ARG(Function) function)
+ {
+ dispatcher.dispatch (boost::bind (
+ &SharedHandler::invoke , this,
+ BOOST_ASIO_MOVE_CAST(Function)(function)));
+ }
+ */
+
+ template
+ void invoke (BOOST_ASIO_MOVE_ARG(Function) f);
+
+ virtual void invoke (invoked_type& invoked) = 0;
+ virtual void* allocate (std::size_t size) = 0;
+ virtual void deallocate (void* p, std::size_t size) = 0;
+ virtual bool is_continuation () = 0;
+ virtual void destroy () = 0;
+
+ static void pure_virtual_called (char const* fileName, int lineNumber);
+
+private:
+ template
+ friend void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandler*);
+ friend void* asio_handler_allocate (std::size_t, SharedHandler*);
+ friend void asio_handler_deallocate (void*, std::size_t, SharedHandler*);
+ friend bool asio_handler_is_continuation (SharedHandler*);
+ friend struct ContainerDeletePolicy ;
+};
+
+//--------------------------------------------------------------------------
+
+// For SharedObjectPtr
+template <>
+struct ContainerDeletePolicy
+{
+ // SharedObjectPtr will use this when
+ // the reference count drops to zero.
+ //
+ inline static void destroy (SharedHandler* handler)
+ {
+ handler->destroy ();
+ }
+};
+
+//--------------------------------------------------------------------------
+//
+// Context execution guarantees
+//
+
+template
+void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandler* handler)
+{
+ handler->invoke (BOOST_ASIO_MOVE_CAST(Function)(f));
+}
+
+inline void* asio_handler_allocate (std::size_t size, SharedHandler* handler)
+{
+ return handler->allocate (size);
+}
+
+inline void asio_handler_deallocate (void* p, std::size_t size, SharedHandler* handler)
+{
+ handler->deallocate (p, size);
+}
+
+inline bool asio_handler_is_continuation (SharedHandler* handler)
+{
+ return handler->is_continuation ();
+}
+
+#endif
diff --git a/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerAllocator.h b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerAllocator.h
new file mode 100644
index 0000000000..404d12a9b2
--- /dev/null
+++ b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerAllocator.h
@@ -0,0 +1,129 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_SHAREDHANDLERALLOCATOR_H_INCLUDED
+#define BEAST_SHAREDHANDLERALLOCATOR_H_INCLUDED
+
+/** Custom Allocator using the allocation hooks from the Handler.
+
+ This class is compatible with std::allocator and can be used in any
+ boost interface which takes a template parameter of type Allocator.
+ This includes boost::function and especially boost::asio::streambuf
+ and relatives. This is vastly more efficient in a variety of situations
+ especially during an upcall and when using stackful coroutines.
+
+ The Allocator holds a reference to the underlying SharedHandler. The
+ SharedHandler will not be destroyed as long as any Allocator is still
+ using it.
+*/
+template
+struct SharedHandlerAllocator
+{
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef T const* const_pointer;
+ typedef T const& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ SharedHandlerAllocator (SharedHandler* handler) noexcept
+ : m_ptr (handler)
+ {
+ }
+
+ SharedHandlerAllocator (SharedHandlerPtr const& handler) noexcept
+ : m_ptr (handler)
+ {
+ }
+
+ template
+ SharedHandlerAllocator (SharedHandlerAllocator const& other)
+ : m_ptr (other.m_ptr)
+ {
+ }
+
+ template
+ struct rebind
+ {
+ typedef SharedHandlerAllocator other;
+ };
+
+ pointer address (reference x) const
+ {
+ return &x;
+ }
+
+ const_pointer address (const_reference x) const
+ {
+ return &x;
+ }
+
+ pointer allocate (size_type n) const
+ {
+ size_type const bytes = n * sizeof (value_type);
+ return static_cast (m_ptr->allocate (bytes));
+ }
+
+ void deallocate (pointer p, size_type n) const
+ {
+ size_type const bytes = n * sizeof (value_type);
+ m_ptr->deallocate (p, bytes);
+ }
+
+ size_type max_size () const noexcept
+ {
+ return std::numeric_limits ::max () / sizeof (value_type);
+ }
+
+ void construct (pointer p, const_reference val) const
+ {
+ ::new ((void *)p) value_type (val);
+ }
+
+ void destroy (pointer p) const
+ {
+ p->~value_type ();
+ }
+
+private:
+ template
+ friend struct SharedHandlerAllocator;
+ friend class SharedHandler;
+
+ SharedHandlerPtr m_ptr;
+};
+
+//------------------------------------------------------------------------------
+
+template
+void SharedHandler::invoke (BOOST_ASIO_MOVE_ARG(Function) f)
+{
+#if BEAST_USE_HANDLER_ALLOCATIONS
+ // The allocator will hold a reference to the SharedHandler
+ // so that we can safely destroy the function object.
+ invoked_type invoked (BOOST_ASIO_MOVE_CAST(Function)(f),
+ SharedHandlerAllocator (this));
+#else
+ invoked_type invoked (BOOST_ASIO_MOVE_CAST(Function)(f));
+#endif
+ invoke (invoked);
+}
+
+#endif
diff --git a/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerPtr.h b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerPtr.h
new file mode 100644
index 0000000000..b6a6ef4fe0
--- /dev/null
+++ b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerPtr.h
@@ -0,0 +1,307 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_SHAREDHANDLERPTR_H_INCLUDED
+#define BEAST_SHAREDHANDLERPTR_H_INCLUDED
+
+/** RAII container for a SharedHandler.
+
+ This object behaves exactly like a SharedHandler except that it
+ merely contains a shared pointer to the underlying SharedHandler.
+ All calls are forwarded to the underlying SharedHandler, and all
+ of the execution safety guarantees are met by forwarding them through
+ to the underlying SharedHandler.
+*/
+class SharedHandlerPtr
+{
+protected:
+ typedef boost::system::error_code error_code;
+
+public:
+ // For asio::async_result<>
+ typedef void result_type;
+
+ /** Construct a null handler.
+ A null handler cannot be called. It can, however, be checked
+ for validity by calling isNull, and later assigned.
+
+ @see isNull, isNotNull
+ */
+ inline SharedHandlerPtr () noexcept
+ {
+ }
+
+ /** Construct from an existing SharedHandler.
+ Ownership of the handler is transferred to the container.
+ */
+ inline SharedHandlerPtr (SharedHandler* handler)
+ : m_ptr (handler)
+ {
+ }
+
+ /** Construct a reference from an existing container.
+ */
+ inline SharedHandlerPtr (SharedHandlerPtr const& other) noexcept
+ : m_ptr (other.m_ptr)
+ {
+ }
+
+ /** Assign a reference from an existing container. */
+ inline SharedHandlerPtr& operator= (SharedHandlerPtr const& other) noexcept
+ {
+ m_ptr = other.m_ptr;
+ return *this;
+ }
+
+#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ /** Move-construct a reference from an existing container.
+ The other container is set to a null handler.
+ */
+ inline SharedHandlerPtr (SharedHandlerPtr&& other) noexcept
+ : m_ptr (other.m_ptr)
+ {
+ other.m_ptr = nullptr;
+ }
+
+ /** Move-assign a reference from an existing container.
+ The other container is set to a null handler.
+ */
+ inline SharedHandlerPtr& operator= (SharedHandlerPtr&& other) noexcept
+ {
+ m_ptr = other.m_ptr;
+ other.m_ptr = nullptr;
+ return *this;
+ }
+#endif
+
+ /** Returns true if the handler is a null handler. */
+ inline bool isNull () const noexcept
+ {
+ return m_ptr == nullptr;
+ }
+
+ /** Returns true if the handler is not a null handler. */
+ inline bool isNotNull () const noexcept
+ {
+ return m_ptr != nullptr;
+ }
+
+ /** Dereference the container.
+ This returns a reference to the underlying SharedHandler object.
+ */
+ inline SharedHandler& operator* () const noexcept
+ {
+ return *m_ptr;
+ }
+
+ /** SharedHandler member access.
+ This lets you call functions directly on the SharedHandler.
+ */
+ inline SharedHandler* operator-> () const noexcept
+ {
+ return m_ptr.get ();
+ }
+
+ /** Retrieve the SharedHandler as a Context.
+
+ This can be used for invoking functions in the context:
+
+ @code
+
+ template
+ void callOnHandler (Function f, SharedHandlerPtr ptr)
+ {
+ boost::asio_handler_invoke (f, ptr.get ());
+ }
+
+ @endcode
+ */
+ inline SharedHandler* get () const noexcept
+ {
+ return m_ptr.get ();
+ }
+
+ /** Invoke the SharedHandler with signature void(void)
+ Normally this is called by a dispatcher, you shouldn't call it directly.
+ */
+ inline void operator() () const
+ {
+ (*m_ptr)();
+ }
+
+ /** Invoke the SharedHandler with signature void(error_code)
+ Normally this is called by a dispatcher, you shouldn't call it directly.
+ */
+ inline void operator() (error_code const& ec) const
+ {
+ (*m_ptr)(ec);
+ }
+
+ /** Invoke the SharedHandler with signature void(error_code, size_t)
+ Normally this is called by a dispatcher, you shouldn't call it directly.
+ */
+ inline void operator() (error_code const& ec, std::size_t bytes_transferred) const
+ {
+ (*m_ptr)(ec, bytes_transferred);
+ }
+
+private:
+ // These ensure that SharedHandlerPtr invocations adhere to
+ // the asio::io_service execution guarantees of the underlying SharedHandler.
+ //
+ template
+ friend void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandlerPtr*);
+ friend void* asio_handler_allocate (std::size_t, SharedHandlerPtr*);
+ friend void asio_handler_deallocate (void*, std::size_t, SharedHandlerPtr*);
+ friend bool asio_handler_is_continuation (SharedHandlerPtr*);
+
+ SharedHandler::Ptr m_ptr;
+};
+
+//--------------------------------------------------------------------------
+//
+// Context execution guarantees
+//
+
+template
+inline void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandlerPtr* ptr)
+{
+ boost_asio_handler_invoke_helpers::
+ invoke
+ (BOOST_ASIO_MOVE_CAST(Function)(f), *ptr->get ());
+}
+
+inline void* asio_handler_allocate (std::size_t size, SharedHandlerPtr* ptr)
+{
+ return boost_asio_handler_alloc_helpers::
+ allocate (size, *ptr->get ());
+}
+
+inline void asio_handler_deallocate (void* p, std::size_t size, SharedHandlerPtr* ptr)
+{
+ boost_asio_handler_alloc_helpers::
+ deallocate (p, size, *ptr->get ());
+}
+
+inline bool asio_handler_is_continuation (SharedHandlerPtr* ptr)
+{
+#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
+ return boost_asio_handler_cont_helpers::
+ is_continuation (*ptr->get ());
+#else
+ return false;
+#endif
+}
+
+//--------------------------------------------------------------------------
+//
+// Helpers
+//
+//--------------------------------------------------------------------------
+
+// CompletionHandler
+//
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/CompletionHandler.html
+//
+template
+SharedHandlerPtr newCompletionHandler (
+ BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
+}
+
+// AcceptHandler
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AcceptHandler.html
+//
+template
+SharedHandlerPtr newAcceptHandler (
+ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+}
+
+// ConnectHandler
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ConnectHandler.html
+//
+template
+SharedHandlerPtr newConnectHandler (
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+}
+
+// ShutdownHandler
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ShutdownHandler.html
+//
+template
+SharedHandlerPtr newShutdownHandler(
+ BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
+}
+
+// HandshakeHandler
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/HandshakeHandler.html
+//
+template
+SharedHandlerPtr newHandshakeHandler(
+ BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
+}
+
+// ReadHandler
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ReadHandler.html
+//
+template
+SharedHandlerPtr newReadHandler(
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+// WriteHandler
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/WriteHandler.html
+//
+template
+SharedHandlerPtr newWriteHandler(
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+}
+
+// BufferedHandshakeHandler
+// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/BufferedHandshakeHandler.html
+//
+template
+SharedHandlerPtr newBufferedHandshakeHandler(
+ BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
+{
+ return newSharedHandlerContainer (
+ BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
+}
+
+#endif
diff --git a/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerType.h b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerType.h
new file mode 100644
index 0000000000..bb7bca2a0f
--- /dev/null
+++ b/Subtrees/beast/modules/beast_asio/async/beast_SharedHandlerType.h
@@ -0,0 +1,233 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_SHAREDHANDLERTYPE_H_INCLUDED
+#define BEAST_SHAREDHANDLERTYPE_H_INCLUDED
+
+/** An instance of SharedHandler that wraps an existing Handler.
+
+ The wrapped handler will meet all the execution guarantees of
+ the original Handler object.
+*/
+template
+class SharedHandlerType : public SharedHandler
+{
+protected:
+ SharedHandlerType (std::size_t size,
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ : m_size (size)
+ , m_handler (BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+ ~SharedHandlerType ()
+ {
+
+ }
+
+ void invoke (invoked_type& invoked)
+ {
+ boost_asio_handler_invoke_helpers::
+ invoke (invoked, m_handler);
+ }
+
+ void* allocate (std::size_t size)
+ {
+ return boost_asio_handler_alloc_helpers::
+ allocate (size, m_handler);
+ }
+
+ void deallocate (void* p, std::size_t size)
+ {
+ boost_asio_handler_alloc_helpers::
+ deallocate (p, size, m_handler);
+ }
+
+ bool is_continuation ()
+ {
+#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
+ return boost_asio_handler_cont_helpers::
+ is_continuation (m_handler);
+#else
+ return false;
+#endif
+ }
+
+ // Called by our ContainerDeletePolicy hook to destroy the
+ // object. We need this because we allocated it using a custom
+ // allocator. Destruction is tricky, the algorithm is as follows:
+ //
+ // First we move-assign the handler to our stack. If the build
+ // doesn't support move-assignment it will be a copy, still ok.
+ // We convert 'this' to a pointer to the polymorphic base, to
+ // ensure that the following direct destructor call will reach
+ // the most derived class. Finally, we deallocate the memory
+ // using the handler that is local to the stack.
+ //
+ // For this to work we need to make sure regular operator delete
+ // is never called for our object (it's private). We also need
+ // the size from the original allocation, which we saved at
+ // the time of construction.
+ //
+ void destroy ()
+ {
+#if BEAST_USE_HANDLER_ALLOCATIONS
+ Handler local (BOOST_ASIO_MOVE_CAST(Handler)(m_handler));
+ std::size_t const size (m_size);
+ SharedHandler* const shared (static_cast (this));
+ shared->~SharedHandler ();
+ boost_asio_handler_alloc_helpers::
+ deallocate (shared, size, local);
+#else
+ delete this;
+#endif
+ }
+
+#if BEAST_USE_HANDLER_ALLOCATIONS
+ // If these somehow get called, bad things will happen
+ //
+ void* operator new (std::size_t)
+ {
+ return pure_virtual_called (__FILE__, __LINE__);
+ }
+
+ void operator delete (void*)
+ {
+ return pure_virtual_called (__FILE__, __LINE__);
+ }
+#endif
+
+protected:
+ std::size_t const m_size;
+ Handler m_handler;
+};
+
+//--------------------------------------------------------------------------
+//
+// A SharedHandlerType for this signature:
+// void(void)
+//
+template
+class PostSharedHandlerType : public SharedHandlerType
+{
+public:
+ PostSharedHandlerType (std::size_t size,
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ : SharedHandlerType (size,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+protected:
+ void operator() ()
+ {
+ this->m_handler ();
+ }
+};
+
+//--------------------------------------------------------------------------
+//
+// A SharedHandlerType for this signature:
+// void(error_code)
+//
+template
+class ErrorSharedHandlerType : public SharedHandlerType
+{
+public:
+ ErrorSharedHandlerType (std::size_t size,
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ : SharedHandlerType (size,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+protected:
+ void operator() (boost::system::error_code const& ec)
+ {
+ this->m_handler (ec);
+ }
+};
+
+//--------------------------------------------------------------------------
+//
+// A SharedHandlerType for this signature:
+// void(error_code, size_t)
+//
+template
+class TransferSharedHandlerType : public SharedHandlerType
+{
+public:
+ TransferSharedHandlerType (std::size_t size,
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ : SharedHandlerType (size,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+protected:
+ void operator() (boost::system::error_code const& ec,
+ std::size_t bytes_transferred)
+ {
+ this->m_handler (ec, bytes_transferred);
+ }
+};
+
+//--------------------------------------------------------------------------
+//
+// These specializations will make sure we don't do
+// anything silly like wrap ourselves in our own wrapper...
+//
+#if 1
+template <>
+class PostSharedHandlerType
+{
+};
+
+template <>
+class ErrorSharedHandlerType
+{
+};
+template <>
+class TransferSharedHandlerType
+{
+};
+#endif
+
+
+//--------------------------------------------------------------------------
+
+/** Construct a wrapped handler using the context's allocation hooks.
+*/
+template class Container, typename Handler>
+Container * newSharedHandlerContainer (BOOST_ASIO_MOVE_ARG(Handler) handler)
+{
+ typedef Container ContainerType;
+ std::size_t const size (sizeof (ContainerType));
+#if BEAST_USE_HANDLER_ALLOCATIONS
+ Handler local (BOOST_ASIO_MOVE_CAST(Handler)(handler));
+ void* const p (boost_asio_handler_alloc_helpers::
+ allocate (size, local));
+ return ::new (p) ContainerType (size, BOOST_ASIO_MOVE_CAST(Handler)(local));
+#else
+ void* const p = ::operator new (size);
+ return ::new (p) ContainerType (size, BOOST_ASIO_MOVE_CAST(Handler)(handler));
+#endif
+}
+
+#endif
diff --git a/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h b/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h
index 006d624137..14b972f4f2 100644
--- a/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h
+++ b/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h
@@ -34,21 +34,48 @@ public:
typedef Buffer value_type;
typedef typename std::vector ::const_iterator const_iterator;
+ /** Construct a null buffer.
+ This is the equivalent of @ref asio::null_buffers.
+ */
BufferType ()
: m_size (0)
{
}
- template
- explicit BufferType (OtherBuffers const& buffers)
- : m_size (0)
+ /** Construct a BufferType from an existing BufferSequence.
+ @see assign
+ */
+ template
+ BufferType (BufferSequence const& buffers)
{
+ assign (buffers);
+ }
+
+ /** Assign a BufferType from an existing BufferSequence.
+ @see assign
+ */
+ template
+ BufferType & operator= (BufferSequence const& buffers)
+ {
+ return assign (buffers);
+ }
+
+ /** Assign a BufferType from an existing BufferSequence
+ A copy is not made. The data is still owned by the original
+ BufferSequence object. This merely points to that data.
+ */
+ template
+ BufferType & assign (BufferSequence const& buffers)
+ {
+ m_size = 0;
+ m_buffers.clear ();
m_buffers.reserve (std::distance (buffers.begin (), buffers.end ()));
- BOOST_FOREACH (typename OtherBuffers::value_type buffer, buffers)
+ BOOST_FOREACH (typename BufferSequence::value_type buffer, buffers)
{
m_size += boost::asio::buffer_size (buffer);
m_buffers.push_back (buffer);
}
+ return *this;
}
/** Determine the total size of all buffers.
@@ -91,7 +118,10 @@ private:
std::vector m_buffers;
};
+/** A single linear read-only buffer. */
typedef boost::asio::const_buffer ConstBuffer;
+
+/** A single linear writable buffer. */
typedef boost::asio::mutable_buffer MutableBuffer;
/** Meets the requirements of ConstBufferSequence */
diff --git a/Subtrees/beast/modules/beast_asio/basics/beast_HandlerCall.cpp b/Subtrees/beast/modules/beast_asio/basics/beast_HandlerCall.cpp
deleted file mode 100644
index ce20265a63..0000000000
--- a/Subtrees/beast/modules/beast_asio/basics/beast_HandlerCall.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-//
-// Context
-//
-//------------------------------------------------------------------------------
-
-HandlerCall::Context::Context (Call* call) noexcept
- : m_call (call)
-{
- bassert (m_call != nullptr);
-}
-
-HandlerCall::Context::Context () noexcept
- : m_call (nullptr)
-{
-}
-
-HandlerCall::Context::Context (Context const& other) noexcept
- : m_call (other.m_call)
-{
-}
-
-HandlerCall::Context::Context (HandlerCall const& handler) noexcept
- : m_call (handler.m_call.get ())
-{
-}
-
-HandlerCall::Context& HandlerCall::Context::operator= (Context other) noexcept
-{
- m_call = other.m_call;
- return *this;
-}
-
-bool HandlerCall::Context::operator== (Call const* call) const noexcept
-{
- return m_call == call;
-}
-
-bool HandlerCall::Context::operator!= (Call const* call) const noexcept
-{
- return m_call != call;
-}
-
-bool HandlerCall::Context::isComposed () const noexcept
-{
- return m_call->is_continuation ();
-}
-
-bool HandlerCall::Context::isNull () const noexcept
-{
- return m_call == nullptr;
-}
-
-bool HandlerCall::Context::isNotNull () const noexcept
-{
- return m_call != nullptr;
-}
-
-bool HandlerCall::Context::operator== (Context other) const noexcept
-{
- return m_call == other.m_call;
-}
-
-bool HandlerCall::Context::operator!= (Context other) const noexcept
-{
- return m_call != other.m_call;
-}
-
-void* HandlerCall::Context::allocate (std::size_t size) const
-{
- return m_call->allocate (size);
-}
-
-void HandlerCall::Context::deallocate (void* p, std::size_t size) const
-{
- m_call->deallocate (p, size);
-}
-
-//------------------------------------------------------------------------------
-//
-// Call
-//
-//------------------------------------------------------------------------------
-
-HandlerCall::Call::Call (Context context) noexcept
- : m_context (context.isNull () ? Context (this) : context)
- , m_is_continuation (false)
- , m_is_final_continuation (false)
-{
-}
-
-HandlerCall::Call::~Call ()
-{
-}
-
-HandlerCall::Context HandlerCall::Call::getContext () const noexcept
-{
- return m_context;
-}
-
-bool HandlerCall::Call::is_continuation () const noexcept
-{
- // If this goes off it means someone isn't calling getContext()!
- bassert (m_context == this);
- return m_is_continuation;
-}
-
-void HandlerCall::Call::set_continuation () noexcept
-{
- // Setting it twice means some code is sloppy!
- bassert (! m_is_continuation);
-
- m_is_continuation = true;
-}
-
-void HandlerCall::Call::set_final_continuation () noexcept
-{
- // Soemone called endComposed without calling beginComposed!
- bassert (m_is_continuation);
- // When true, we will clear
- // m_is_continuation on our next completion
- m_is_final_continuation = true;
-}
-
-void HandlerCall::Call::check_continuation () noexcept
-{
- if (m_is_final_continuation)
- {
- bassert (m_is_continuation);
-
- m_is_continuation = false;
- m_is_final_continuation = false;
- }
-}
-
-void HandlerCall::Call::operator() ()
-{
- check_continuation ();
- dispatch ();
-}
-
-void HandlerCall::Call::operator() (error_code const& ec)
-{
- check_continuation ();
- dispatch (ec);
-}
-
-void HandlerCall::Call::operator() (error_code const& ec, std::size_t bytes_transferred)
-{
- check_continuation ();
- dispatch (ec, bytes_transferred);
-}
-
-void HandlerCall::Call::dispatch ()
-{
- pure_virtual_called ();
-}
-
-void HandlerCall::Call::dispatch (error_code const&)
-{
- pure_virtual_called ();
-}
-
-void HandlerCall::Call::dispatch (error_code const&, std::size_t)
-{
- pure_virtual_called ();
-}
-
-void* HandlerCall::Call::pure_virtual_called ()
-{
- // These shouldn't be getting called. But since the object returned
- // by most implementations of bind have operator() up to high arity
- // levels, it is not generally possible to write a traits test that
- // works in all scenarios for detecting a particular signature of a
- // handler.
- //
- fatal_error ("pure virtual called");
- return nullptr;
-}
-
-//------------------------------------------------------------------------------
-//
-// HandlerCall
-//
-//------------------------------------------------------------------------------
-
-HandlerCall::HandlerCall () noexcept
-{
-}
-
-HandlerCall::HandlerCall (HandlerCall const& other) noexcept
- : m_call (other.m_call)
-{
-}
-
-HandlerCall& HandlerCall::operator= (HandlerCall const& other) noexcept
-{
- m_call = other.m_call;
- return *this;
-}
-
-bool HandlerCall::isNull () const noexcept
-{
- return m_call == nullptr;
-}
-
-bool HandlerCall::isNotNull () const noexcept
-{
- return m_call != nullptr;
-}
-
-HandlerCall::Context HandlerCall::getContext () const noexcept
-{
- bassert (m_call != nullptr);
- return m_call->getContext ();
-}
-
-bool HandlerCall::isFinal () const noexcept
-{
- return m_call->getContext () == m_call.get ();
-}
-
-HandlerCall const& HandlerCall::beginComposed () const noexcept
-{
- // If this goes off it means that your handler is
- // already sharing a context with another handler!
- // You have to call beginComposed on the original handler.
- //
- bassert (isFinal ());
- m_call->set_continuation ();
- return *this;
-}
-
-HandlerCall const& HandlerCall::endComposed () const noexcept
-{
- // If this goes off it means that your handler is
- // already sharing a context with another handler!
- // You have to call beginComposed on the original handler.
- //
- bassert (isFinal ());
- m_call->set_final_continuation ();
- return *this;
-}
-
-void HandlerCall::operator() () const
-{
- (*m_call)();
-}
-
-void HandlerCall::operator() (error_code const& ec) const
-{
- (*m_call)(ec);
-}
-
-void HandlerCall::operator() (error_code const& ec, std::size_t bytes_transferred) const
-{
- (*m_call)(ec, bytes_transferred);
-}
-
-//------------------------------------------------------------------------------
-//
-// Specializations
-//
-//------------------------------------------------------------------------------
-
-void ContainerDeletePolicy ::destroy (HandlerCall::Call* call)
-{
- call->destroy ();
-}
-
-//------------------------------------------------------------------------------
-
-void* asio_handler_allocate (std::size_t size, HandlerCall* call)
-{
- // Always go through the call's context.
- return call->getContext ().allocate (size);
-}
-
-void* asio_handler_allocate (std::size_t size, HandlerCall::Call* call)
-{
- // Always go through the call's context.
- return call->getContext ().allocate (size);
-}
-
-void* asio_handler_allocate (std::size_t size, HandlerCall::Context* context)
-{
- return context->allocate (size);
-}
-
-//------------------------------------------------------------------------------
-
-void asio_handler_deallocate (void* p, std::size_t size, HandlerCall* call)
-{
- // Always go through the call's context.
- call->getContext ().deallocate (p, size);
-}
-
-void asio_handler_deallocate (void* p, std::size_t size, HandlerCall::Call* call)
-{
- // Always go through the call's context.
- call->getContext ().deallocate (p, size);
-}
-
-void asio_handler_deallocate (void* p, std::size_t size, HandlerCall::Context* context)
-{
- context->deallocate (p, size);
-}
-
-//------------------------------------------------------------------------------
-
-bool asio_handler_is_continuation (HandlerCall* call)
-{
- return call->getContext().isComposed ();
-}
-
-bool asio_handler_is_continuation (HandlerCall::Call* call)
-{
- return call->getContext().isComposed ();
-}
-
-bool asio_handler_is_continuation (HandlerCall::Context*)
-{
- // Something is horribly wrong if we're trying to
- // use a Context as a completion handler?
- //
- fatal_error ("A function was unexpectedly called.");
- return false;
-}
diff --git a/Subtrees/beast/modules/beast_asio/basics/beast_HandlerCall.h b/Subtrees/beast/modules/beast_asio/basics/beast_HandlerCall.h
deleted file mode 100644
index 2fc0cb150e..0000000000
--- a/Subtrees/beast/modules/beast_asio/basics/beast_HandlerCall.h
+++ /dev/null
@@ -1,1004 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_HANDLERCALL_H_INCLUDED
-#define BEAST_HANDLERCALL_H_INCLUDED
-
-/** A polymorphic Handler that can wrap any other handler.
-
- This is very lightweight container that just holds a shared pointer
- to the actual handler. This means it can be copied cheaply. The
- allocation and deallocation of the handler is performed according
- to the requirements of asio_handler_allocate and asio_handler_delete.
- All calls also satisfy the safety guarantees of asio_handler_invoke.
-
- All constructors will take ownership of the passed in handler
- if your compiler has MoveConstructible and MoveAssignable support enabled.
-
- Supports these concepts:
- DefaultConstructible
- CopyConstructible
- CopyAssignable
- Destructible
-*/
-class HandlerCall
-{
-private:
- typedef boost::system::error_code error_code;
- typedef boost::function invoked_type;
-
- // Forward declarations needed for friendship
- template
- struct CallType;
- struct Call;
-
-public:
- typedef void result_type;
-
- struct Context;
-
- //--------------------------------------------------------------------------
-
- /** HandlerCall construction tags.
-
- These tags are used at the end of HandlerCall constructor parameter
- lists to tell it what kind of Handler you are passing. For example:
-
- @code
-
- struct MyClass
- {
- void on_connect (error_code const& ec);
-
- void connect (Address address)
- {
- HandlerCall myHandler (
- bind (&MyClass::foo, this),
- Connect ());
-
- socket.async_connect (address, myHandler);
- }
- };
-
- @endcode
-
- It would be nice if we could deduce the type of handler from the template
- argument alone, but the return value of most implementations of bind seem
- to satisfy the traits of ANY handler so that was scrapped.
- */
- /** @{ */
- // These are the three basic supported function signatures
- //
- // ComposedConnectHandler is to-do
- //
- struct Post { }; // void()
- struct Error { }; // void(error_code)
- struct Transfer { }; // void(error_code, std::size_t)
-
- // CompletionHandler
- //
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/CompletionHandler.html
- //
- typedef Post Completion;
-
- // AcceptHandler
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AcceptHandler.html
- //
- typedef Error Accept;
-
- // ConnectHandler
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ConnectHandler.html
- //
- typedef Error Connect;
-
- // ShutdownHandler
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ShutdownHandler.html
- //
- typedef Error Shutdown;
-
- // HandshakeHandler
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/HandshakeHandler.html
- //
- typedef Error Handshake;
-
- // ReadHandler
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ReadHandler.html
- //
- typedef Transfer Read;
-
- // WriteHandler
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/WriteHandler.html
- //
- typedef Transfer Write;
-
- // BufferedHandshakeHandler
- // http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/BufferedHandshakeHandler.html
- //
- typedef Transfer BufferedHandshake;
- /** @} */
-
- //--------------------------------------------------------------------------
-
- /** Construct a null HandlerCall.
-
- A default constructed handler has no associated call. Passing
- it as a handler to an asynchronous operation will result in
- undefined behavior. This constructor exists so that you can do
- things like have a class member "originalHandler" which starts
- out as null, and then later assign it. Routines are provided to
- test the handler against null.
- */
- HandlerCall () noexcept;
-
- /** Construct a HandlerCall.
-
- Handler must meet this requirement:
- CompletionHandler
-
- HandlerCall will meet this requirement:
- CompletionHandler
- */
- /** @{ */
- template
- HandlerCall (Post, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : m_call (construct (Context (),
- BOOST_ASIO_MOVE_CAST(Handler)(handler)))
- {
- }
-
- template
- HandlerCall (Post, Context context, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : m_call (construct (context,
- BOOST_ASIO_MOVE_CAST(Handler)(handler)))
- {
- }
- /** @} */
-
- /** Construct a HandlerCall with one bound parameter.
-
- Produce a CompletionHandler that includes one bound parameter.
- This can be useful if you want to call io_service::post() on
- the handler and you need to give it an already existing value,
- like an error_code.
-
- Invoking operator() on the HandlerCall will be the same as:
-
- @code
-
- handler (arg1);
-
- @endcode
-
- Handler must meet one of these requirements:
- AcceptHandler
- ConnectHandler
- ShutdownHandler
- HandshakeHandler
-
- HandlerCall will meet this requirement:
- CompletionHandler
- */
- /** @{ */
- template
- HandlerCall (Post, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1)
- : m_call (construct (Context (),
- BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1))
- {
- }
-
- template
- HandlerCall (Post, Context context, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1)
- : m_call (construct (context,
- BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1))
- {
- }
- /** @} */
-
- /** Construct a HandlerCall with two bound parameters.
-
- Produce a CompletionHandler that includes two bound parameters.
- This can be useful if you want to call io_service::post() on
- the handler and you need to give it two already existing values,
- like an error_code and bytes_transferred.
-
- Invoking operator() on the HandlerCall will be the same as:
-
- @code
-
- handler (arg1, arg2);
-
- @endcode
-
- Handler must meet one of these requirements:
- ReadHandler
- WriteHandler
- BufferedHandshakeHandler
-
- The HandlerCall will meet these requirements:
- CompletionHandler
- */
- /** @{ */
- template
- HandlerCall (Post, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1, Arg2 arg2)
- : m_call (construct (Context (),
- BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1, arg2))
- {
- }
-
- template
- HandlerCall (Post, Context context, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1, Arg2 arg2)
- : m_call (construct (context,
- BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1, arg2))
- {
- }
- /** @} */
-
- /** Construct a HandlerCall from a handler that takes an error_code
-
- Handler must meet one of these requirements:
- AcceptHandler
- ConnectHandler
- ShutdownHandler
- HandshakeHandler
-
- The HandlerCall will meet these requirements:
- AcceptHandler
- ConnectHandler
- ShutdownHandler
- HandshakeHandler
- */
- /** @{ */
- template
- HandlerCall (Error, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : m_call (construct (Context (),
- BOOST_ASIO_MOVE_CAST(Handler)(handler)))
- {
- }
-
- template
- HandlerCall (Error, Context context, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : m_call (construct (context,
- BOOST_ASIO_MOVE_CAST(Handler)(handler)))
- {
- }
- /** @} */
-
- /** Construct a HandlerCall from a handler that takes an error_code and std::size
-
- Handler must meet one of these requirements:
- ReadHandler
- WriteHandler
- BufferedHandshakeHandler
-
- The HandlerCall will meet these requirements:
- ReadHandler
- WriteHandler
- BufferedHandshakeHandler
- */
- /** @{ */
- template
- HandlerCall (Transfer, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : m_call (construct (Context (),
- BOOST_ASIO_MOVE_CAST(Handler)(handler)))
- {
- }
-
- template
- HandlerCall (Transfer, Context context, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : m_call (construct (context,
- BOOST_ASIO_MOVE_CAST(Handler)(handler)))
- {
- }
- /** @} */
-
- /** Copy construction and assignment.
-
- HandlerCall is a very lightweight object that holds a shared
- pointer to the wrapped handler. It is cheap to copy and pass
- around.
-
- Construction and assignment from other HandlerCall objects
- executes in constant time, does not allocate or free memory,
- and invokes no methods calls on the wrapped handler, except
- for the case where the last reference on an existing handler
- is removed.
- */
- /** @{ */
- HandlerCall (HandlerCall const& other) noexcept;
- HandlerCall& operator= (HandlerCall const& other) noexcept;
- /** @} */
-
- //--------------------------------------------------------------------------
-
- /** Returns true if the HandlerCall is null.
-
- A null HandlerCall object may not be passed to
- an asynchronous completion function.
- */
- bool isNull () const noexcept;
-
- /** Returns true if the HandlerCall is not null. */
- bool isNotNull () const noexcept;
-
- /** Retrieve the context associated with a handler.
-
- The context will only be valid while the handler exists. In particular,
- if the handler is dispatched all references to its context will become
- invalid, and undefined behavior will result.
-
- The typical use case is to acquire the context from a caller provided
- completion handler, and use the context in a series of composed
- operations. At the conclusion of the composed operations, the original
- handler is invoked and the context is no longer needed.
-
- Various methods are provided for easily creating your own completion
- handlers that are associated with an existing context.
- */
- Context getContext () const noexcept;
-
- /** Determine if this handler is the final handler in a composed chain.
- A Context is usually shared during a composed operation.
- Normally you won't need to call this but it's useful for diagnostics.
- Really what this means it that the context is its own wrapped handler.
- */
- bool isFinal () const noexcept;
-
- /** Mark this handler as part of a composed operation.
-
- This is only valid to call if the handler is not already sharing
- the context of another handler (i.e. it is already part of a
- composed operation).
-
- Any handlers that share the same context will result in true being
- passed to the asio_is_continuation_hook. When you are ready to
- issue the final call to the original handler (which will also
- destroy the context), call endComposed on the original
- handler.
-
- To be clear, beginComposed and endComposed are called on the same
- HandlerCall object, and that object was not constructed from another
- context.
-
- @see isComposed, endComposed
- */
- HandlerCall const& beginComposed () const noexcept;
-
- /** Indicate the end of a composed operation.
-
- A composed operation starts with a handler that uses itself as its own
- context. The composed operation issues new asynchronous calls with its
- own callback, using the original handler's context. To optimize the
- strategy for calling completion handlers, call beginComposed.
- */
- HandlerCall const& endComposed () const noexcept;
-
- /** Invoke the wrapped handler.
-
- Normally you will not need to call this yourself. Since this is a
- polymorphic wrapper, any attempt to use an operator that doesn't
- correspond to the signature of the wrapped handler (taking into
- account arguments bound at construction), will result in a fatal
- error at run-time.
- */
- /** @{ */
- void operator() () const;
- void operator() (error_code const& ec) const;
- void operator() (error_code const& ec, std::size_t bytes_transferred) const;
- /** @} */
-
- //--------------------------------------------------------------------------
-
- /** The context of execution of a particular handler.
-
- When writing composed operations (a sequence of asynchronous function
- calls), it is important that the intermediate handlers run in the same
- context as the handler originally provided to signal the end of the
- composed operation.
-
- An object of this type abstracts the execution context of any handler.
- You can extract the context from an existing handler and associate
- new handlers you create with that context. This allows composed
- operations to be written easily, lifting the burden of meeting the
- composed operation requirements.
-
- In all cases, the Context will only be valid while the original handler
- exists. It is the caller's responsibility to manage the usage and
- lifetimes of these objects.
-
- Context objects are lightweight and just hold a reference to the
- underlying context. They are cheap to copy and pass around.
-
- Supports these concepts:
- DefaultConstructible
- CopyConstructible
- CopyAssignable
- Destructible
- */
- struct Context
- {
- /** Construct a null Context.
- When a null Context is specified as the Context to use when
- creating a HandlerCall, it means to use the wrapped handler
- as its own context. This is the default behavior.
- */
- Context () noexcept;
-
- /** Construct a Context from another Context. */
- Context (Context const& other) noexcept;
-
- /** Construct a Context from an existing handler's Context. */
- Context (HandlerCall const& handler) noexcept;
-
- /** Assign this Context from another Context. */
- Context& operator= (Context other) noexcept;
-
- /** Determine if this context is a composed asynchronous operation.
-
- When a handler begins a composed operation it becomes its own
- context (it is not constructed with a specified context). When
- a composed operation starts, this will return true for all
- handlers which share the context including the original handler.
-
- You have to indicate that a composed operation is starting by
- calling beginComposed on the original handler, performing
- your operations using its context, and then call endComposed
- before calling the original handler.
-
- @see beginComposed, endComposed
- */
- bool isComposed () const noexcept;
-
- /** Determine whether or not this Context is a null Context.
- Note that a non-null Context is no guarantee of
- the validity of the context.
- */
- /** @{ */
- bool isNull () const noexcept;
- bool isNotNull () const noexcept;
- /** @} */
-
- /** Compare two contexts.
- This determines if the two contexts refer to the same underlying
- completion handler and would have the same execution guarantees.
- The behavior is undefined if either of the contexts have been
- destroyed.
- */
- /** @{ */
- bool operator== (Context other) const noexcept;
- bool operator!= (Context other) const noexcept;
- /** @} */
-
- /** Allocate and deallocate memory.
- This takes into account any hooks installed by the context.
- Normally you wont need to call this unless you are writing your
- own asio_handler_invoke hook, or creating wrapped handlers.
- */
- /** @{ */
- void* allocate (std::size_t size) const;
- void deallocate (void* p, std::size_t size) const;
- /** @} */
-
- /** Invoke the specified Function on the context.
-
- This is equivalent to the following:
-
- @code
-
- template
- void callOnContext (Function f, Context& context)
- {
- using boost_asio_handler_invoke_helpers;
- invoke (f, context);
- }
-
- @endcode
-
- Usually you won't need to call this unless you
- are writing your own asio_handler_invoke hook.
-
- The boost::function object is created partially on the
- stack, using a custom Allocator which calls into the handler's
- context to perform allocation and deallocation. We take ownership
- of the passed Function object.
-
- All of the safety guarantees of the original context are preserved
- when going through this invoke function.
- */
- template
- void invoke (BOOST_ASIO_MOVE_ARG(Function) f)
- {
- invoked_type invoked (BOOST_ASIO_MOVE_CAST(Function)(f),
- Allocator (*this));
- m_call->invoke (invoked);
- }
-
- bool operator== (Call const* call) const noexcept;
- bool operator!= (Call const* call) const noexcept;
-
- private:
- template
- friend struct CallType;
- friend struct Call;
-
- Context (Call* call) noexcept;
-
- // Note that we only store a pointer here. If the original
- // Call is destroyed, the context will become invalid.
- //
- Call* m_call;
- };
-
-private:
- //--------------------------------------------------------------------------
- //
- // Implementation
- //
- //--------------------------------------------------------------------------
-
- // These construct the Call, a reference counted polymorphic wrapper around
- // the handler and its context. We use MoveAssignable (rvalue-references)
- // assignments to take ownership of the object and bring it to our stack.
- // From there, we use the context's hooked allocation function to create a
- // single piece of memory to hold our wrapper. Then we use placement new to
- // construct the wrapper. The wrapper uses rvalue assignment to take
- // ownership of the handler from the stack.
-
- template class Container, typename Handler>
- static Call* construct (Context context, BOOST_ASIO_MOVE_ARG(Handler) handler)
- {
- typedef Container ContainerType;
- Handler local (BOOST_ASIO_MOVE_CAST(Handler)(handler));
- std::size_t const size (sizeof (ContainerType));
- void* const p = boost_asio_handler_alloc_helpers::
- allocate (size, local);
- return ::new (p) ContainerType (context, size,
- BOOST_ASIO_MOVE_CAST(Handler)(local));
- }
-
- template class Container,
- typename Handler, typename Arg1>
- static Call* construct (Context context, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1)
- {
- typedef Container ContainerType;
- Handler local (BOOST_ASIO_MOVE_CAST(Handler)(handler));
- std::size_t const size (sizeof (ContainerType));
- void* const p = boost_asio_handler_alloc_helpers::
- allocate (size, local);
- return ::new (p) ContainerType (context, size,
- BOOST_ASIO_MOVE_CAST(Handler)(local), arg1);
- }
-
- template class Container,
- typename Handler, typename Arg1, typename Arg2>
- static Call* construct (Context context, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1, Arg2 arg2)
- {
- typedef Container ContainerType;
- Handler local (BOOST_ASIO_MOVE_CAST(Handler)(handler));
- std::size_t const size (sizeof (ContainerType));
- void* const p = boost_asio_handler_alloc_helpers::
- allocate (size, local);
- return ::new (p) ContainerType (context, size,
- BOOST_ASIO_MOVE_CAST(Handler)(local), arg1, arg2);
- }
-
- //--------------------------------------------------------------------------
- //
- // Custom Allocator compatible with std::allocator and boost::function
- // which uses the underlying context to allocate memory. This is vastly
- // more efficient in a variety of situations especially during an upcall.
- //
- // The context must be valid for the duration of the invocation.
- //
- template
- struct Allocator
- {
- typedef T value_type;
- typedef T* pointer;
- typedef T& reference;
- typedef T const* const_pointer;
- typedef T const& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- // Make sure this is the right context!
- //
- explicit Allocator (Context context)
- : m_context (context)
- {
- }
-
- template
- Allocator (Allocator const& other)
- : m_context (other.m_context)
- {
- }
-
- template
- struct rebind
- {
- typedef Allocator other;
- };
-
- pointer address (reference x) const
- {
- return &x;
- }
-
- const_pointer address (const_reference x) const
- {
- return &x;
- }
-
- pointer allocate (size_type n) const
- {
- size_type const bytes = n * sizeof (value_type);
- return static_cast (m_context.allocate (bytes));
- }
-
- void deallocate (pointer p, size_type n) const
- {
- size_type const bytes = n * sizeof (value_type);
- m_context.deallocate (p, bytes);
- }
-
- size_type max_size () const noexcept
- {
- return std::numeric_limits ::max () / sizeof (value_type);
- }
-
- void construct (pointer p, const_reference val) const
- {
- ::new ((void *)p) value_type (val);
- }
-
- void destroy (pointer p) const
- {
- p->~value_type ();
- }
-
- private:
- template
- friend struct Allocator;
-
- // The context must remain valid for the lifetime of the allocator.
- //
- Context m_context;
- };
-
- //--------------------------------------------------------------------------
- //
- // Abstract handler wrapper
- //
- struct Call : public SharedObject
- {
- public:
- explicit Call (Context context) noexcept;
- ~Call ();
-
- Context getContext () const noexcept;
-
- // Determine if the completion handler is a continuation
- // of a composed operation. It's generally not possible
- // to know this from here, so there's an interface to
- // set the flag.
- //
- // Our asio_handler_is_continuation hook calls this.
- //
- bool is_continuation () const noexcept;
- void set_continuation () noexcept;
- void set_final_continuation () noexcept;
-
- void operator() ();
- void operator() (error_code const&);
- void operator() (error_code const&, std::size_t);
-
- virtual void* allocate (std::size_t) = 0;
- virtual void deallocate (void*, std::size_t) = 0;
- virtual void destroy () = 0;
-
- //----------------------------------------------------------------------
-
- protected:
- void check_continuation () noexcept;
-
- virtual void dispatch ();
- virtual void dispatch (error_code const&);
- virtual void dispatch (error_code const&, std::size_t);
-
- static void* pure_virtual_called ();
-
- Context const m_context;
- bool m_is_continuation;
- bool m_is_final_continuation;
-
- private:
- // called by Context
- friend struct Context;
- virtual void invoke (invoked_type&) = 0;
- };
-
- // Required for gaining access to our hooks
- //
- friend struct ContainerDeletePolicy ;
-
- //--------------------------------------------------------------------------
-
- // Holds the original handler with all of its type information.
- // Can also perform the invoke, allocate, and deallocate operations
- // in the same context as the original handler.
- //
- template
- struct CallType : Call
- {
- // We take ownership of the handler here, through move assignment.
- // The size parameter corresponds to how much we allocated using
- // the custom allocator, and is required for deallocation.
- //
- // If the passed context is null, we will use the handler itself
- // as the context (this is what normally happens when you pass a
- // handler into an asynchronous function operation).
- //
- // Context must have Call as a base or this will result in
- // undefined behavior.
- //
- CallType (Context context, std::size_t size, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : Call (context)
- , m_size (size)
- , m_handler (BOOST_ASIO_MOVE_CAST(Handler)(handler))
- {
- }
-
- ~CallType ()
- {
-
- }
-
- // Allocate using the original handler as the context.
- //
- void* allocate (std::size_t bytes)
- {
- // If this goes off someone didn't call getContext()!
- bassert (m_context == this);
- return boost_asio_handler_alloc_helpers::
- allocate (bytes, m_handler);
- }
-
- // Deallocate using the handlers context.
- // Note that the original size is required.
- //
- void deallocate (void* p, std::size_t size)
- {
- // If this goes off someone didn't call getContext()!
- bassert (m_context == this);
- boost_asio_handler_alloc_helpers::
- deallocate (p, size, m_handler);
- }
-
- // Invoke the specified function on the handlers context.
- // invoked has this signature void(void).
- //
- void invoke (invoked_type& invoked)
- {
- // If this goes off someone didn't call getContext()!
- bassert (m_context == this);
- boost_asio_handler_invoke_helpers::
- invoke (invoked, m_handler);
- }
-
- // Called by our ContainerDeletePolicy hook to destroy the
- // object. We need this because we allocated it using a custom
- // allocator. Destruction is tricky, the algorithm is as follows:
- //
- // First we move-assign the handler to our stack. If the build
- // doesn't support move-assignment it will be a copy, still ok.
- // We convert 'this' to a pointer to the polymorphic base, to
- // ensure that the following direct destructor call will reach
- // the most derived class. Finally, we deallocate the memory
- // using the handler that is local to the stack.
- //
- // For this to work we need to make sure regular operator delete
- // is never called for our object (it's private). We also need
- // the size from the original allocation, which we saved at
- // the time of construction.
- //
- void destroy ()
- {
- // Move the handler onto our stack so we have
- // a context in which to perform the deallcation.
- Handler local (BOOST_ASIO_MOVE_CAST(Handler)(m_handler));
- std::size_t const size (m_size); // save the size member
- Call* const call (dynamic_cast (this));
- call->~Call ();
- boost_asio_handler_alloc_helpers::
- deallocate (call, size, local);
- }
-
- // These better not be getting called since we use our own allocators.
- //
- // NOTE Couldn't make them private since GCC complained.
- //
- void* operator new (std::size_t)
- {
- return pure_virtual_called ();
- }
-
- void operator delete (void*)
- {
- pure_virtual_called ();
- }
-
- private:
- std::size_t const m_size;
-
- protected:
- Handler m_handler;
- };
-
- //--------------------------------------------------------------------------
-
- template
- struct PostCallType : CallType
- {
- PostCallType (Context context, std::size_t size, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : CallType (context, size, BOOST_ASIO_MOVE_CAST(Handler)(handler))
- {
- }
-
- void dispatch ()
- {
- this->m_handler ();
- }
- };
-
- template
- struct PostCallType1 : CallType
- {
- PostCallType1 (Context context, std::size_t size, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1)
- : CallType (context, size, BOOST_ASIO_MOVE_CAST(Handler)(handler))
- , m_arg1 (arg1)
- {
- }
-
- void dispatch ()
- {
- this->m_handler (m_arg1);
- }
-
- Arg1 m_arg1;
- };
-
- template
- struct PostCallType2 : CallType
- {
- PostCallType2 (Context context, std::size_t size, BOOST_ASIO_MOVE_ARG(Handler) handler, Arg1 arg1, Arg2 arg2)
- : CallType (context, size, BOOST_ASIO_MOVE_CAST(Handler)(handler))
- , m_arg1 (arg1)
- , m_arg2 (arg2)
- {
- }
-
- void dispatch ()
- {
- this->m_handler (m_arg1, m_arg2);
- }
-
- Arg1 m_arg1;
- Arg2 m_arg2;
- };
-
- template
- struct ErrorCallType : CallType
- {
- ErrorCallType (Context context, std::size_t size, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : CallType (context, size, BOOST_ASIO_MOVE_CAST(Handler)(handler))
- {
- }
-
- void dispatch (error_code const& ec)
- {
- this->m_handler (ec);
- }
- };
-
- template
- struct TransferCallType : CallType
- {
- TransferCallType (Context context, std::size_t size, BOOST_ASIO_MOVE_ARG(Handler) handler)
- : CallType (context, size, BOOST_ASIO_MOVE_CAST(Handler)(handler))
- {
- }
-
- void dispatch (error_code const& ec, std::size_t bytes_transferred)
- {
- this->m_handler (ec, bytes_transferred);
- }
- };
-
-private:
- template
- friend void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function), HandlerCall*);
- friend void* asio_handler_allocate (std::size_t, HandlerCall*);
- friend void asio_handler_deallocate (void*, std::size_t, HandlerCall*);
-
- template
- friend void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function), Call*);
- friend void* asio_handler_allocate (std::size_t, Call*);
- friend void asio_handler_deallocate (void*, std::size_t, Call*);
-
- friend bool asio_handler_is_continuation (HandlerCall* call);
- friend bool asio_handler_is_continuation (HandlerCall::Call* call);
- friend bool asio_handler_is_continuation (HandlerCall::Context* context);
-
- SharedObjectPtr m_call;
-};
-
-//------------------------------------------------------------------------------
-//
-// Specializations
-//
-// ContainerDeletePolicy
-// asio_handler_invoke
-// asio_handler_allocate
-// asio_handler_deallocate
-//
-
-template <>
-struct ContainerDeletePolicy
-{
- // SharedObjectPtr will use this when
- // the reference count drops to zero.
- //
- static void destroy (HandlerCall::Call* call);
-};
-
-template
-void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, HandlerCall::Context* context)
-{
- context->invoke (BOOST_ASIO_MOVE_CAST(Function)(f));
-}
-
-template
-void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, HandlerCall* call)
-{
- // Always go through the call's context.
- call->getContext().invoke (BOOST_ASIO_MOVE_CAST(Function)(f));
-}
-
-template
-void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, HandlerCall::Call* call)
-{
- // Always go through the call's context.
- call->getContext().invoke (BOOST_ASIO_MOVE_CAST(Function)(f));
-}
-
-void* asio_handler_allocate (std::size_t size, HandlerCall* call);
-void* asio_handler_allocate (std::size_t size, HandlerCall::Call* call);
-void* asio_handler_allocate (std::size_t size, HandlerCall::Context* context);
-
-void asio_handler_deallocate (void* p, std::size_t size, HandlerCall* call);
-void asio_handler_deallocate (void* p, std::size_t size, HandlerCall::Call* call);
-void asio_handler_deallocate (void* p, std::size_t size, HandlerCall::Context* context);
-
-bool asio_handler_is_continuation (HandlerCall* call);
-bool asio_handler_is_continuation (HandlerCall::Call* call);
-bool asio_handler_is_continuation (HandlerCall::Context* context);
-
-//------------------------------------------------------------------------------
-
-#endif
diff --git a/Subtrees/beast/modules/beast_asio/beast_asio.cpp b/Subtrees/beast/modules/beast_asio/beast_asio.cpp
index a4b780995f..72b45cfa78 100644
--- a/Subtrees/beast/modules/beast_asio/beast_asio.cpp
+++ b/Subtrees/beast/modules/beast_asio/beast_asio.cpp
@@ -26,7 +26,8 @@
namespace beast
{
-#include "basics/beast_HandlerCall.cpp"
+#include "async/beast_SharedHandler.cpp"
+
#include "basics/beast_PeerRole.cpp"
#include "sockets/beast_SocketBase.cpp"
@@ -35,6 +36,7 @@ namespace beast
#include "handshake/beast_HandshakeDetectLogicPROXY.cpp"
+#include "tests/beast_PeerTest.cpp"
#include "tests/beast_TestPeerBasics.cpp"
#include "tests/beast_TestPeerLogic.cpp"
#include "tests/beast_TestPeerLogicProxyClient.cpp"
@@ -42,8 +44,8 @@ namespace beast
#include "tests/beast_TestPeerLogicSyncClient.cpp"
#include "tests/beast_TestPeerLogicAsyncServer.cpp"
#include "tests/beast_TestPeerLogicAsyncClient.cpp"
-
-#include "tests/beast_PeerTest.cpp"
#include "tests/beast_TestPeerUnitTests.cpp"
+#include "system/beast_BoostUnitTests.cpp"
+
}
diff --git a/Subtrees/beast/modules/beast_asio/beast_asio.h b/Subtrees/beast/modules/beast_asio/beast_asio.h
index 234a8f960c..0b67985bbd 100644
--- a/Subtrees/beast/modules/beast_asio/beast_asio.h
+++ b/Subtrees/beast/modules/beast_asio/beast_asio.h
@@ -40,15 +40,36 @@
// Must come before boost includes to fix the bost placeholders.
#include "../beast_core/beast_core.h"
-/* This module requires boost and possibly OpenSSL */
+// This module requires boost and possibly OpenSSL
#include "system/beast_BoostIncludes.h"
+// Checking overrides replaces unimplemented stubs with pure virtuals
+#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
+# define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 0
+#endif
+#if BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
+# define BEAST_SOCKET_VIRTUAL = 0
+#else
+# define BEAST_SOCKET_VIRTUAL
+#endif
+
+// A potentially dangerous but powerful feature which
+// might need to be turned off to see if it fixes anything.
+//
+#ifndef BEAST_USE_HANDLER_ALLOCATIONS
+# define BEAST_USE_HANDLER_ALLOCATIONS 1
+#endif
+
namespace beast
{
// Order matters
+ #include "async/beast_SharedHandler.h"
+ #include "async/beast_SharedHandlerType.h"
+ #include "async/beast_SharedHandlerPtr.h"
+ #include "async/beast_ComposedAsyncOperation.h"
+#include "async/beast_SharedHandlerAllocator.h"
-#include "basics/beast_HandlerCall.h"
#include "basics/beast_BufferType.h"
#include "basics/beast_FixedInputBuffer.h"
#include "basics/beast_PeerRole.h"
@@ -63,9 +84,8 @@ namespace beast
#include "handshake/beast_HandshakeDetectLogicPROXY.h"
#include "handshake/beast_HandshakeDetectLogicSSL2.h"
#include "handshake/beast_HandshakeDetectLogicSSL3.h"
-#include "handshake/beast_HandshakeDetectStream.h"
-
-#include "streams/beast_PrefilledReadStream.h"
+#include "handshake/beast_HandshakeDetector.h"
+#include "handshake/beast_PrefilledReadStream.h"
#include "tests/beast_TestPeerBasics.h"
#include "tests/beast_TestPeer.h"
diff --git a/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectStream.h b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectStream.h
deleted file mode 100644
index 4c31953da9..0000000000
--- a/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectStream.h
+++ /dev/null
@@ -1,293 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#ifndef BEAST_HANDSHAKEDETECTSTREAM_H_INCLUDED
-#define BEAST_HANDSHAKEDETECTSTREAM_H_INCLUDED
-
-/** A stream that can detect a handshake.
-*/
-/** @{ */
-template
-class HandshakeDetectStream
-{
-protected:
- typedef boost::system::error_code error_code;
-
-public:
- typedef Logic LogicType;
-
- /** Called when the state is known.
-
- This could be called from any thread, most likely an io_service
- thread but don't rely on that.
-
- The Callback must be allocated via operator new.
- */
- struct Callback
- {
- virtual ~Callback () { }
-
- /** Called for synchronous ssl detection.
-
- Note that the storage for the buffers passed to the
- callback is owned by the detector class and becomes
- invalid when the detector class is destroyed, which is
- a common thing to do from inside your callback.
-
- @param ec A modifiable error code that becomes the return
- value of handshake.
- @param buffers The bytes that were read in.
- @param is_ssl True if the sequence is an ssl handshake.
- */
- virtual void on_detect (Logic& logic,
- error_code& ec, ConstBuffers const& buffers) = 0;
-
- virtual void on_async_detect (Logic& logic,
- error_code const& ec, ConstBuffers const& buffers,
- HandlerCall const& origHandler) = 0;
- };
-};
-
-//------------------------------------------------------------------------------
-
-template
-class HandshakeDetectStreamType
- : public HandshakeDetectStream
- , public boost::asio::ssl::stream_base
- , public boost::asio::socket_base
-{
-private:
- typedef boost::system::error_code error_code;
-
- typedef HandshakeDetectStreamType this_type;
- typedef boost::asio::streambuf buffer_type;
- typedef typename boost::remove_reference ::type stream_type;
-
-public:
- typedef typename HandshakeDetectStream ::Callback CallbackType;
-
- /** This takes ownership of the callback.
- The callback must be allocated with operator new.
- */
- template
- HandshakeDetectStreamType (CallbackType* callback, Arg& arg)
- : m_callback (callback)
- , m_next_layer (arg)
- , m_stream (m_next_layer)
- {
- }
-
- // This puts bytes that you already have into the detector buffer
- // Any leftovers will be given to the callback.
- // A copy of the data is made.
- //
- template
- void fill (ConstBufferSequence const& buffers)
- {
- m_buffer.commit (boost::asio::buffer_copy (
- m_buffer.prepare (boost::asio::buffer_size (buffers)),
- buffers));
- }
-
- // basic_io_object
-
- boost::asio::io_service& get_io_service ()
- {
- return m_next_layer.get_io_service ();
- }
-
- // basic_socket
-
- typedef typename stream_type::protocol_type protocol_type;
- typedef typename stream_type::lowest_layer_type lowest_layer_type;
-
- lowest_layer_type& lowest_layer ()
- {
- return m_next_layer.lowest_layer ();
- }
-
- lowest_layer_type const& lowest_layer () const
- {
- return m_next_layer.lowest_layer ();
- }
-
- // ssl::stream
-
- error_code handshake (handshake_type type, error_code& ec)
- {
- return do_handshake (type, ec, ConstBuffers ());
- }
-
- template
- BEAST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (error_code))
- async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
- {
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- boost::asio::detail::async_result_init<
- HandshakeHandler, void (error_code)> init(
- BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
- // init.handler is copied
- m_origHandler = HandlerCall (
- BOOST_ASIO_MOVE_CAST(HandshakeHandler)
- (HandshakeHandler(init.handler)));
- async_do_handshake (type, ConstBuffers ());
- return init.result.get();
-#else
- m_origHandler = HandlerCall (
- BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
- async_do_handshake (type, ConstBuffers ());
-#endif
- }
-
- //--------------------------------------------------------------------------
-
- error_code do_handshake (handshake_type, error_code& ec, ConstBuffers const& buffers)
- {
- ec = error_code ();
-
- // Transfer caller data to our buffer.
- m_buffer.commit (boost::asio::buffer_copy (m_buffer.prepare (
- boost::asio::buffer_size (buffers)), buffers));
-
- do
- {
- std::size_t const available = m_buffer.size ();
- std::size_t const needed = m_logic.max_needed ();
- if (available < needed)
- {
- buffer_type::mutable_buffers_type buffers (
- m_buffer.prepare (needed - available));
- m_buffer.commit (m_next_layer.read_some (buffers, ec));
- }
-
- if (! ec)
- {
- m_logic.analyze (m_buffer.data ());
-
- if (m_logic.finished ())
- {
- // consume what we used (for SSL its 0)
- std::size_t const consumed = m_logic.bytes_consumed ();
- bassert (consumed <= m_buffer.size ());
- m_buffer.consume (consumed);
- m_callback->on_detect (m_logic.get (), ec,
- ConstBuffers (m_buffer.data ()));
- break;
- }
-
- // If this fails it means we will never finish
- check_postcondition (available < needed);
- }
- }
- while (! ec);
-
- return ec;
- }
-
- //--------------------------------------------------------------------------
-
- void async_do_handshake (handshake_type type, ConstBuffers const& buffers)
- {
- // Get the execution context from the original handler
- // and signal the beginning of our composed operation.
- //
- //m_origHandler.beginComposed ();
- m_context = m_origHandler.getContext ();
-
- bassert (m_context.isNotNull ());
-
- // Transfer caller data to our buffer.
- // We commit the bytes in on_async_read_some.
- //
- std::size_t const bytes_transferred (boost::asio::buffer_copy (
- m_buffer.prepare (boost::asio::buffer_size (buffers)), buffers));
-
- // bootstrap the asynchronous loop
- on_async_read_some (error_code (), bytes_transferred);
- }
-
- // asynchronous version of the synchronous loop found in handshake ()
- //
- void on_async_read_some (error_code const& ec, std::size_t bytes_transferred)
- {
- if (! ec)
- {
- m_buffer.commit (bytes_transferred);
-
- std::size_t const available = m_buffer.size ();
- std::size_t const needed = m_logic.max_needed ();
-
- if (bytes_transferred > 0)
- m_logic.analyze (m_buffer.data ());
-
- if (m_logic.finished ())
- {
- // consume what we used (for SSL its 0)
- std::size_t const consumed = m_logic.bytes_consumed ();
- bassert (consumed <= m_buffer.size ());
- m_buffer.consume (consumed);
-
- // The composed operation has completed and
- // the original handler will eventually get called.
- //
- //m_origHandler.endComposed ();
- m_callback->on_async_detect (m_logic.get (), ec,
- ConstBuffers (m_buffer.data ()), m_origHandler);
- return;
- }
-
- // If this fails it means we will never finish
- check_postcondition (available < needed);
-
- buffer_type::mutable_buffers_type buffers (m_buffer.prepare (
- needed - available));
-
- // Perform the asynchronous operation using the context
- // of the original handler. This ensures that we meet the
- // execution safety requirements of the handler.
- //
- HandlerCall handler (HandlerCall::Read (), m_context,
- boost::bind (&this_type::on_async_read_some, this,
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- m_next_layer.async_read_some (buffers, handler);
-
- return;
- }
-
- // Error condition
-
- //m_origHandler.endComposed ();
- m_callback->on_async_detect (m_logic.get (), ec,
- ConstBuffers (m_buffer.data ()), m_origHandler);
- }
-
-private:
- ScopedPointer m_callback;
- Stream m_next_layer;
- buffer_type m_buffer;
- boost::asio::buffered_read_stream m_stream;
- HandshakeDetectLogicType m_logic;
- HandlerCall m_origHandler;
- HandlerCall m_origBufferedHandler;
- HandlerCall::Context m_context;
-};
-/** @} */
-
-#endif
diff --git a/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetector.h b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetector.h
new file mode 100644
index 0000000000..a53296ba64
--- /dev/null
+++ b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetector.h
@@ -0,0 +1,206 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_HANDSHAKEDETECTOR_H_INCLUDED
+#define BEAST_HANDSHAKEDETECTOR_H_INCLUDED
+
+//------------------------------------------------------------------------------
+
+/** A wrapper to decode the handshake data on a Stream.
+
+ Stream must meet these requirements
+
+ For detect:
+ SyncReadStream
+
+ For async_detect:
+ AsyncReadStream
+
+ Logic must meet this requirement:
+ HandshakeDetectLogic
+*/
+template
+class HandshakeDetectorType
+{
+protected:
+ typedef boost::system::error_code error_code;
+
+public:
+ Logic& getLogic ()
+ {
+ return m_logic.get ();
+ }
+
+ //--------------------------------------------------------------------------
+
+ /** Synchronous handshake detect.
+ The bytes from the input sequence in the specified buffer
+ are used first.
+ */
+ template
+ error_code detect (Stream& stream,
+ boost::asio::basic_streambuf & buffer)
+ {
+ typedef boost::asio::basic_streambuf BufferType;
+
+ error_code ec;
+
+ do
+ {
+ m_logic.analyze (buffer.data ());
+
+ if (m_logic.finished ())
+ {
+ // consume what we used (for SSL its 0)
+ std::size_t const consumed = m_logic.bytes_consumed ();
+ bassert (consumed <= buffer.size ());
+ buffer.consume (consumed);
+ break;
+ }
+
+ std::size_t const available = buffer.size ();
+ std::size_t const needed = m_logic.max_needed ();
+
+ // If postcondition fails, loop will never end
+ if (meets_postcondition (available < needed))
+ {
+ typename BufferType::mutable_buffers_type buffers (
+ buffer.prepare (needed - available));
+ buffer.commit (stream.read_some (buffers, ec));
+ }
+ }
+ while (! ec);
+
+ return ec;
+ }
+
+ //--------------------------------------------------------------------------
+
+ /** Asynchronous handshake detect.
+ The bytes from the input sequence in the specified buffer
+ are used first.
+
+ DetectHandler must have this signature:
+ void(error_code)
+ */
+ template
+ void async_detect (Stream& stream,
+ boost::asio::basic_streambuf & buffer,
+ BOOST_ASIO_MOVE_ARG(DetectHandler) handler)
+ {
+ async_detect (stream, buffer, SharedHandlerPtr (
+ new ErrorSharedHandlerType (
+ BOOST_ASIO_MOVE_CAST(DetectHandler)(handler))));
+ }
+
+ template
+ void async_detect (Stream& stream,
+ boost::asio::basic_streambuf & buffer,
+ SharedHandlerPtr handler)
+ {
+ typedef AsyncOp OpType;
+ OpType* const op = new AsyncOp (
+ m_logic, stream, buffer, handler);
+ stream.get_io_service ().wrap (SharedHandlerPtr (op))
+ (error_code (), 0);
+ }
+
+private:
+ template
+ struct AsyncOp : ComposedAsyncOperation
+ {
+ typedef boost::asio::basic_streambuf BufferType;
+
+ AsyncOp (HandshakeDetectLogicType & logic, Stream& stream,
+ BufferType& buffer, SharedHandlerPtr const& handler)
+ : ComposedAsyncOperation (sizeof (*this), handler)
+ , m_logic (logic)
+ , m_stream (stream)
+ , m_buffer (buffer)
+ , m_handler (handler)
+ , m_running (false)
+ {
+ }
+
+ // Set breakpoint to prove it gets destroyed
+ ~AsyncOp ()
+ {
+ }
+
+ void operator() (error_code const& ec_, size_t bytes_transferred)
+ {
+ m_running = true;
+
+ error_code ec (ec_);
+
+ if (! ec)
+ {
+ m_buffer.commit (bytes_transferred);
+
+ m_logic.analyze (m_buffer.data ());
+
+ if (!m_logic.finished ())
+ {
+ std::size_t const available = m_buffer.size ();
+ std::size_t const needed = m_logic.max_needed ();
+
+ // If postcondition fails, loop will never end
+ if (meets_postcondition (available < needed))
+ {
+ typename BufferType::mutable_buffers_type buffers (
+ m_buffer.prepare (needed - available));
+
+ m_stream.async_read_some (buffers, SharedHandlerPtr (this));
+ }
+
+ return;
+ }
+
+ std::size_t const consumed = m_logic.bytes_consumed ();
+ m_buffer.consume (consumed);
+ }
+
+ // Finalize with a call to the original handler.
+ m_stream.get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST (SharedHandlerPtr)(m_handler))
+ (ec);
+ }
+
+ bool is_continuation ()
+ {
+ return m_running
+#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
+ || boost_asio_handler_cont_helpers::is_continuation (m_handler);
+#endif
+ ;
+ }
+
+ private:
+ HandshakeDetectLogicType & m_logic;
+ Stream& m_stream;
+ BufferType& m_buffer;
+ SharedHandlerPtr m_handler;
+ bool m_running;
+ };
+
+private:
+ HandshakeDetectLogicType m_logic;
+};
+
+#endif
diff --git a/Subtrees/beast/modules/beast_asio/streams/beast_PrefilledReadStream.h b/Subtrees/beast/modules/beast_asio/handshake/beast_PrefilledReadStream.h
similarity index 82%
rename from Subtrees/beast/modules/beast_asio/streams/beast_PrefilledReadStream.h
rename to Subtrees/beast/modules/beast_asio/handshake/beast_PrefilledReadStream.h
index 135fb30c45..7747398a94 100644
--- a/Subtrees/beast/modules/beast_asio/streams/beast_PrefilledReadStream.h
+++ b/Subtrees/beast/modules/beast_asio/handshake/beast_PrefilledReadStream.h
@@ -72,10 +72,10 @@ public:
template
void fill (ConstBufferSequence const& buffers)
{
- using namespace boost;
// We don't assume the caller's buffers will
// remain valid for the lifetime of this object.
//
+ using namespace boost;
m_buffer.commit (asio::buffer_copy (
m_buffer.prepare (asio::buffer_size (buffers)),
buffers));
@@ -116,76 +116,6 @@ public:
return m_next_layer.close(ec);
}
- template
- std::size_t write_some (ConstBufferSequence const& buffers)
- {
- return m_next_layer.write_some (buffers);
- }
-
- template
- std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec)
- {
- return m_next_layer.write_some (buffers, ec);
- }
-
- template
- std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec)
- {
- ec = error_code ();
- if (m_buffer.size () > 0)
- {
- std::size_t const bytes_transferred = boost::asio::buffer_copy (
- buffers, m_buffer.data ());
- m_buffer.consume (bytes_transferred);
- return bytes_transferred;
- }
- return m_next_layer.read_some (buffers, ec);
- }
-
- template
- BEAST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (error_code, std::size_t))
- async_read_some (MutableBufferSequence const& buffers,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
- {
- using namespace boost;
- if (m_buffer.size () > 0)
- {
- std::size_t const bytes_transferred = asio::buffer_copy (
- buffers, m_buffer.data ());
- m_buffer.consume (bytes_transferred);
-
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- asio::detail::async_result_init <
- ReadHandler, void (error_code, std::size_t)> init (
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
-
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- ReadHandler(init.handler), // handler is copied
- error_code (), bytes_transferred));
-
- return init.result.get();
-
-#else
- return get_io_service ().post (HandlerCall (HandlerCall::Post (),
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler),
- error_code (), bytes_transferred));
-
-#endif
- }
-
- return m_next_layer.async_read_some (buffers,
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
- }
-
- template
- BEAST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (error_code, std::size_t))
- async_write_some (ConstBufferSequence const& buffers,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
- {
- return m_next_layer.async_write_some (buffers,
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
- }
-
template
std::size_t read_some (MutableBufferSequence const& buffers)
{
@@ -196,6 +126,62 @@ public:
return amount;
}
+ template
+ std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec)
+ {
+ if (m_buffer.size () > 0)
+ {
+ ec = error_code ();
+ std::size_t const bytes_transferred = boost::asio::buffer_copy (
+ buffers, m_buffer.data ());
+ m_buffer.consume (bytes_transferred);
+ return bytes_transferred;
+ }
+ return m_next_layer.read_some (buffers, ec);
+ }
+
+ template
+ std::size_t write_some (ConstBufferSequence const& buffers)
+ {
+ error_code ec;
+ std::size_t const amount = write_some (buffers, ec);
+ if (ec)
+ throw_error (ec, __FILE__, __LINE__);
+ return amount;
+ }
+
+ template
+ std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec)
+ {
+ return m_next_layer.write_some (buffers, ec);
+ }
+
+ template
+ void async_read_some (MutableBufferSequence const& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ if (m_buffer.size () > 0)
+ {
+ std::size_t const bytes_transferred = boost::asio::buffer_copy (
+ buffers, m_buffer.data ());
+ m_buffer.consume (bytes_transferred);
+ get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) (
+ error_code (), bytes_transferred);
+ return;
+ }
+ m_next_layer.async_read_some (buffers,
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+
+ template
+ void async_write_some (ConstBufferSequence const& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ m_next_layer.async_write_some (buffers,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
private:
Stream m_next_layer;
boost::asio::streambuf m_buffer;
diff --git a/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.cpp b/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.cpp
index d6e858bb00..d90f9eb9ac 100644
--- a/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.cpp
+++ b/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.cpp
@@ -21,6 +21,8 @@ Socket::~Socket ()
{
}
+#if ! BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
+
//-----------------------------------------------------------------------------
//
// basic_io_object
@@ -28,7 +30,7 @@ Socket::~Socket ()
boost::asio::io_service& Socket::get_io_service ()
{
- pure_virtual ();
+ pure_virtual_called (__FILE__, __LINE__);
return *static_cast (nullptr);
}
@@ -39,29 +41,29 @@ boost::asio::io_service& Socket::get_io_service ()
void* Socket::lowest_layer (char const*) const
{
- pure_virtual ();
+ pure_virtual_called (__FILE__, __LINE__);
return nullptr;
}
void* Socket::native_handle (char const*) const
{
- pure_virtual ();
+ pure_virtual_called (__FILE__, __LINE__);
return nullptr;
}
boost::system::error_code Socket::cancel (boost::system::error_code& ec)
{
- return pure_virtual (ec);
+ return pure_virtual_error (ec, __FILE__, __LINE__);
}
boost::system::error_code Socket::shutdown (shutdown_type, boost::system::error_code& ec)
{
- return pure_virtual (ec);
+ return pure_virtual_error (ec, __FILE__, __LINE__);
}
boost::system::error_code Socket::close (boost::system::error_code& ec)
{
- return pure_virtual (ec);
+ return pure_virtual_error (ec, __FILE__, __LINE__);
}
//------------------------------------------------------------------------------
@@ -71,22 +73,14 @@ boost::system::error_code Socket::close (boost::system::error_code& ec)
boost::system::error_code Socket::accept (Socket&, boost::system::error_code& ec)
{
- return pure_virtual (ec);
+ return pure_virtual_error (ec, __FILE__, __LINE__);
}
-BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(HandlerCall, void (boost::system::error_code))
-Socket::async_accept (Socket&, HandlerCall const& handler)
+void Socket::async_accept (Socket&, SharedHandlerPtr handler)
{
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- boost::asio::detail::async_result_init<
- HandlerCall, void (boost::system::error_code)> init( handler);
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler, pure_virtual_error ()));
- return init.result.get();
-#else
- get_io_service ().post (HandlerCall (HandlerCall::Post(),
- handler, pure_virtual_error ()));
-#endif
+ get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
+ (pure_virtual_error ());
}
//------------------------------------------------------------------------------
@@ -96,44 +90,30 @@ Socket::async_accept (Socket&, HandlerCall const& handler)
std::size_t Socket::read_some (MutableBuffers const&, boost::system::error_code& ec)
{
- pure_virtual (ec);
+ pure_virtual_called (__FILE__, __LINE__);
+ ec = pure_virtual_error ();
return 0;
}
std::size_t Socket::write_some (ConstBuffers const&, boost::system::error_code& ec)
{
- pure_virtual (ec);
+ pure_virtual_called (__FILE__, __LINE__);
+ ec = pure_virtual_error ();
return 0;
}
-BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(HandlerCall, void (boost::system::error_code, std::size_t))
-Socket::async_read_some (MutableBuffers const&, HandlerCall const& handler)
+void Socket::async_read_some (MutableBuffers const&, SharedHandlerPtr handler)
{
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- boost::asio::detail::async_result_init<
- HandlerCall, void (boost::system::error_code, std::size_t)> init(handler);
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler, pure_virtual_error (), 0));
- return init.result.get();
-#else
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler , pure_virtual_error (), 0));
-#endif
+ get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
+ (pure_virtual_error (), 0);
}
-BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(HandlerCall, void (boost::system::error_code, std::size_t))
-Socket::async_write_some (ConstBuffers const&, HandlerCall const& handler)
+void Socket::async_write_some (ConstBuffers const&, SharedHandlerPtr handler)
{
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- boost::asio::detail::async_result_init<
- HandlerCall, void (boost::system::error_code, std::size_t)> init(handler);
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler, pure_virtual_error (), 0));
- return init.result.get();
-#else
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler, pure_virtual_error (), 0));
-#endif
+ get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
+ (pure_virtual_error (), 0);
}
//--------------------------------------------------------------------------
@@ -148,22 +128,14 @@ bool Socket::needs_handshake ()
boost::system::error_code Socket::handshake (handshake_type, boost::system::error_code& ec)
{
- return pure_virtual (ec);
+ return pure_virtual_error (ec, __FILE__, __LINE__);
}
-BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(HandlerCall, void (boost::system::error_code))
-Socket::async_handshake (handshake_type, HandlerCall const& handler)
+void Socket::async_handshake (handshake_type, SharedHandlerPtr handler)
{
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- boost::asio::detail::async_result_init<
- HandlerCall, void (boost::system::error_code)> init( handler);
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler, pure_virtual_error ()));
- return init.result.get();
-#else
- get_io_service ().post (HandlerCall (HandlerCall::Post(),
- handler, pure_virtual_error ()));
-#endif
+ get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
+ (pure_virtual_error ());
}
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
@@ -171,44 +143,30 @@ Socket::async_handshake (handshake_type, HandlerCall const& handler)
boost::system::error_code Socket::handshake (handshake_type,
ConstBuffers const&, boost::system::error_code& ec)
{
- return pure_virtual (ec);
+ return pure_virtual_error (ec, __FILE__, __LINE__);
}
-BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(HandlerCall, void (boost::system::error_code, std::size_t))
-Socket::async_handshake (handshake_type, ConstBuffers const&, HandlerCall const& handler)
+void Socket::async_handshake (handshake_type, ConstBuffers const&, SharedHandlerPtr handler)
{
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- boost::asio::detail::async_result_init<
- HandlerCall, void (boost::system::error_code, std::size_t)> init(handler);
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler, pure_virtual_error (), 0));
- return init.result.get();
-#else
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler , pure_virtual_error (), 0));
-#endif
+ get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
+ (pure_virtual_error (), 0);
}
#endif
boost::system::error_code Socket::shutdown (boost::system::error_code& ec)
{
- return pure_virtual (ec);
+ return pure_virtual_error (ec, __FILE__, __LINE__);
}
-BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(HandlerCall, void (boost::system::error_code))
-Socket::async_shutdown (HandlerCall const& handler)
+void Socket::async_shutdown (SharedHandlerPtr handler)
{
-#if BEAST_ASIO_HAS_FUTURE_RETURNS
- boost::asio::detail::async_result_init<
- HandlerCall, void (boost::system::error_code, std::size_t)> init (handler);
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler, pure_virtual_error ()));
- return init.result.get();
-#else
- get_io_service ().post (HandlerCall (HandlerCall::Post (),
- handler , pure_virtual_error ()));
-#endif
+ get_io_service ().wrap (
+ BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
+ (pure_virtual_error ());
}
//------------------------------------------------------------------------------
+
+#endif
diff --git a/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.h b/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.h
index cf32a641e9..b60df31146 100644
--- a/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.h
+++ b/Subtrees/beast/modules/beast_asio/sockets/beast_Socket.h
@@ -34,9 +34,6 @@ class Socket
, public boost::asio::ssl::stream_base
, public boost::asio::socket_base
{
-protected:
- typedef boost::system::error_code error_code;
-
public:
virtual ~Socket ();
@@ -45,7 +42,8 @@ public:
// basic_io_object
//
- virtual boost::asio::io_service& get_io_service ();
+ virtual boost::asio::io_service& get_io_service ()
+ BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
//
@@ -57,7 +55,7 @@ public:
else a fatal error will occur.
*/
/** @{ */
- template
+ template
Object& lowest_layer ()
{
Object* object (this->lowest_layer_ptr