Refactor beast::asio:

* New tools for completion handlers:
  - wrap_handler provides composed io_service execution guarantees.
  - bind_handler rebinds arguments to handlers.
  - shared_handler type-erases any completion handler.
  - buffer_sequence type-erases templated BufferSequences
  - abstract_socket replaces Socket
  - socket_wrapper replaces SocketWrapper
  - beast::asio placeholders to work with std::bind

* Removed obsolete classes and functions
  - AbstractHandler
  - ComposedAsyncOperation
  - SharedFunction
  - SharedHandler
  - SharedHandlerAllocator
  - SharedHandlerPtr
  - SharedHandlerType
  - SocketBase
  - SocketWrapperStrand
  - wrapHandler

* Refactored classes to use new tools
  - abstract_socket
  - socket_wrapper
  - HandshakeDetector
  - HttpClientType

* Miscellanous tidying
  - socket classes moved to beast::asio namespace
  - beast asio files provide their own namespace declaration.
  - Fix IsCallPossible conflicting template parameter name
  - Use <boost/get_pointer.hpp> for C++11 compatibility.
  - Remove extraneous include path from build environment.
This commit is contained in:
Vinnie Falco
2014-03-07 20:06:12 -08:00
parent 5478c540cb
commit 6546c30e17
88 changed files with 2709 additions and 3378 deletions

View File

@@ -1,712 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_ABSTRACTHANDLER_H_INCLUDED
#define BEAST_ASIO_ABSTRACTHANDLER_H_INCLUDED
namespace beast {
namespace detail {
struct AbstractHandlerCallBase : SharedObject
{
//typedef SharedFunction <void(void),
// AbstractHandlerAllocator <char> > invoked_type;
typedef SharedFunction <void(void)> invoked_type;
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 invoke (invoked_type& invoked) = 0;
template <typename Function>
void invoke (BEAST_MOVE_ARG(Function) f)
{
invoked_type invoked (BEAST_MOVE_CAST(Function)(f)
//, AbstractHandlerAllocator<char>(this)
);
invoke (invoked);
}
};
/*
template <typename T>
struct AbstractHandlerAllocator
{
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;
AbstractHandlerAllocator (AbstractHandler* handler) noexcept
: m_ptr (handler)
{
}
AbstractHandlerAllocator (SharedPtr <AbstractHandler> const& ptr) noexcept
: m_ptr (ptr)
{
}
template <typename U>
AbstractHandlerAllocator (AbstractHandlerAllocator <U> const& other)
: m_ptr (other.m_ptr)
{
}
template <typename U>
struct rebind
{
typedef AbstractHandlerAllocator <U> 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 <pointer> (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 <size_type>::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 <typename>
friend struct AbstractHandlerAllocator;
friend class AbstractHandler;
SharedPtr <AbstractHandler> m_ptr;
};
*/
}
/** A reference counted, abstract completion handler. */
template <typename Signature, class Allocator = std::allocator <char> >
struct AbstractHandler;
//------------------------------------------------------------------------------
// arity 0
template <class R, class A>
struct AbstractHandler <R (void), A>
{
typedef R result_type;
struct Call : detail::AbstractHandlerCallBase
{ virtual R operator() () = 0; };
template <typename H>
struct CallType : public Call
{
typedef typename A:: template rebind <CallType <H> >::other Allocator;
CallType (BEAST_MOVE_ARG(H) h, A a = A ())
: m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a)
{ }
R operator()()
{ return (m_h)(); }
R operator()() const
{ return (m_h)(); }
void* allocate (std::size_t size)
{ return boost_asio_handler_alloc_helpers::allocate(size, m_h); }
void deallocate (void* pointer, std::size_t size)
{ boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); }
bool is_continuation ()
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
{ return boost_asio_handler_cont_helpers::is_continuation(m_h); }
#else
{ return false; }
#endif
void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked)
{ boost_asio_handler_invoke_helpers::invoke <
typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); }
private:
H m_h;
Allocator m_alloc;
};
template <typename H>
AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ())
: m_call (new (
typename A:: template rebind <CallType <H> >::other (a)
.allocate (1)) CallType <H> (BEAST_MOVE_CAST(H)(h), a))
{ }
R operator() ()
{ return (*m_call)(); }
R operator() () const
{ return (*m_call)(); }
void* allocate (std::size_t size) const { return m_call->allocate(size); }
void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); }
bool is_continuation () const { return m_call->is_continuation(); }
template <typename Function>
void invoke (Function& function) const
{
m_call->invoke(function);
}
template <typename Function>
void invoke (Function const& function) const
{
m_call->invoke(function);
}
private:
SharedPtr <Call> m_call;
};
template <class R, class A>
void* asio_handler_allocate (std::size_t size,
AbstractHandler <R (void), A>* handler)
{
return handler->allocate (size);
}
template <class R, class A>
void asio_handler_deallocate (void* pointer, std::size_t size,
AbstractHandler <R (void), A>* handler)
{
handler->deallocate (pointer, size);
}
template <class R, class A>
bool asio_handler_is_continuation(
AbstractHandler <R (void), A>* handler)
{
return handler->is_continuation();
}
template <typename Function, class R, class A>
void asio_handler_invoke (BEAST_MOVE_ARG(Function) function,
AbstractHandler <R (void), A>* handler)
{
handler->invoke (BEAST_MOVE_CAST(Function)(function));
}
//------------------------------------------------------------------------------
// arity 1
template <class R, class P1, class A>
struct AbstractHandler <R (P1), A>
{
typedef R result_type;
struct Call : detail::AbstractHandlerCallBase
{ virtual R operator() (P1) = 0; };
template <typename H>
struct CallType : public Call
{
typedef typename A:: template rebind <CallType <H> >::other Allocator;
CallType (H h, A a = A ())
: m_h (h)
, m_alloc (a)
{
}
R operator()(P1 p1)
{ return (m_h)(p1); }
R operator()(P1 p1) const
{ return (m_h)(p1); }
void* allocate (std::size_t size)
{ return boost_asio_handler_alloc_helpers::allocate(size, m_h); }
void deallocate (void* pointer, std::size_t size)
{ boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); }
bool is_continuation ()
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
{ return boost_asio_handler_cont_helpers::is_continuation(m_h); }
#else
{ return false; }
#endif
void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked)
{ boost_asio_handler_invoke_helpers::invoke <
typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); }
private:
H m_h;
Allocator m_alloc;
};
template <typename H>
AbstractHandler (H h, A a = A ())
: m_call (new (
typename A:: template rebind <CallType <H> >::other (a)
.allocate (1)) CallType <H> (h, a))
{
}
R operator() (P1 p1)
{ return (*m_call)(p1); }
R operator() (P1 p1) const
{ return (*m_call)(p1); }
void* allocate (std::size_t size) const { return m_call->allocate(size); }
void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); }
bool is_continuation () const { return m_call->is_continuation(); }
template <typename Function>
void invoke (Function& function) const
{
m_call->invoke(function);
}
template <typename Function>
void invoke (Function const& function) const
{
m_call->invoke(function);
}
private:
SharedPtr <Call> m_call;
};
template <class R, class P1, class A>
void* asio_handler_allocate (std::size_t size,
AbstractHandler <R (P1), A>* handler)
{
return handler->allocate (size);
}
template <class R, class P1, class A>
void asio_handler_deallocate (void* pointer, std::size_t size,
AbstractHandler <R (P1), A>* handler)
{
handler->deallocate (pointer, size);
}
template <class R, class P1, class A>
bool asio_handler_is_continuation(
AbstractHandler <R (P1), A>* handler)
{
return handler->is_continuation();
}
template <typename Function, class R, class P1, class A>
void asio_handler_invoke (BEAST_MOVE_ARG(Function) function,
AbstractHandler <R (P1), A>* handler)
{
handler->invoke (BEAST_MOVE_CAST(Function)(function));
}
//------------------------------------------------------------------------------
// arity 2
template <class R, class P1, class P2, class A>
struct AbstractHandler <R (P1, P2), A>
{
typedef R result_type;
struct Call : detail::AbstractHandlerCallBase
{ virtual R operator() (P1, P2) = 0; };
template <typename H>
struct CallType : public Call
{
typedef typename A:: template rebind <CallType <H> >::other Allocator;
CallType (BEAST_MOVE_ARG(H) h, A a = A ())
: m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a)
{ }
R operator()(P1 p1, P2 p2)
{ return (m_h)(p1, p2); }
R operator()(P1 p1, P2 p2) const
{ return (m_h)(p1, p2); }
void* allocate (std::size_t size)
{ return boost_asio_handler_alloc_helpers::allocate(size, m_h); }
void deallocate (void* pointer, std::size_t size)
{ boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); }
bool is_continuation ()
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
{ return boost_asio_handler_cont_helpers::is_continuation(m_h); }
#else
{ return false; }
#endif
void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked)
{ boost_asio_handler_invoke_helpers::invoke <
typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); }
private:
H m_h;
Allocator m_alloc;
};
template <typename H>
AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ())
: m_call (new (
typename A:: template rebind <CallType <H> >::other (a)
.allocate (1)) CallType <H> (BEAST_MOVE_CAST(H)(h), a))
{ }
R operator() (P1 p1, P2 p2)
{ return (*m_call)(p1, p2); }
R operator() (P1 p1, P2 p2) const
{ return (*m_call)(p1, p2); }
void* allocate (std::size_t size) const { return m_call->allocate(size); }
void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); }
bool is_continuation () const { return m_call->is_continuation(); }
template <typename Function>
void invoke (Function& function) const
{
m_call->invoke(function);
}
template <typename Function>
void invoke (Function const& function) const
{
m_call->invoke(function);
}
private:
SharedPtr <Call> m_call;
};
template <class R, class P1, class P2, class A>
void* asio_handler_allocate (std::size_t size,
AbstractHandler <R (P1, P2), A>* handler)
{
return handler->allocate (size);
}
template <class R, class P1, class P2, class A>
void asio_handler_deallocate (void* pointer, std::size_t size,
AbstractHandler <R (P1, P2), A>* handler)
{
handler->deallocate (pointer, size);
}
template <class R, class P1, class P2, class A>
bool asio_handler_is_continuation(
AbstractHandler <R (P1, P2), A>* handler)
{
return handler->is_continuation();
}
template <typename Function, class R, class P1, class P2, class A>
void asio_handler_invoke (BEAST_MOVE_ARG(Function) function,
AbstractHandler <R (P1, P2), A>* handler)
{
handler->invoke (BEAST_MOVE_CAST(Function)(function));
}
//------------------------------------------------------------------------------
// arity 3
template <class R, class P1, class P2, class P3, class A>
struct AbstractHandler <R (P1, P2, P3), A>
{
typedef R result_type;
struct Call : detail::AbstractHandlerCallBase
{ virtual R operator() (P1, P2, P3) = 0; };
template <typename H>
struct CallType : public Call
{
typedef typename A:: template rebind <CallType <H> >::other Allocator;
CallType (BEAST_MOVE_ARG(H) h, A a = A ())
: m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a)
{ }
R operator()(P1 p1, P2 p2, P3 p3)
{ return (m_h)(p1, p2, p3); }
R operator()(P1 p1, P2 p2, P3 p3) const
{ return (m_h)(p1, p2, p3); }
void* allocate (std::size_t size)
{ return boost_asio_handler_alloc_helpers::allocate(size, m_h); }
void deallocate (void* pointer, std::size_t size)
{ boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); }
bool is_continuation ()
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
{ return boost_asio_handler_cont_helpers::is_continuation(m_h); }
#else
{ return false; }
#endif
void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked)
{ boost_asio_handler_invoke_helpers::invoke <
typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); }
private:
H m_h;
Allocator m_alloc;
};
template <typename H>
AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ())
: m_call (new (
typename A:: template rebind <CallType <H> >::other (a)
.allocate (1)) CallType <H> (BEAST_MOVE_CAST(H)(h), a))
{ }
R operator() (P1 p1, P2 p2, P3 p3)
{ return (*m_call)(p1, p2, p3); }
R operator() (P1 p1, P2 p2, P3 p3) const
{ return (*m_call)(p1, p2, p3); }
void* allocate (std::size_t size) const { return m_call->allocate(size); }
void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); }
bool is_continuation () const { return m_call->is_continuation(); }
template <typename Function>
void invoke (Function& function) const
{
m_call->invoke(function);
}
template <typename Function>
void invoke (Function const& function) const
{
m_call->invoke(function);
}
private:
SharedPtr <Call> m_call;
};
template <class R, class P1, class P2, class P3, class A>
void* asio_handler_allocate (std::size_t size,
AbstractHandler <R (P1, P2, P3), A>* handler)
{
return handler->allocate (size);
}
template <class R, class P1, class P2, class P3, class A>
void asio_handler_deallocate (void* pointer, std::size_t size,
AbstractHandler <R (P1, P2, P3), A>* handler)
{
handler->deallocate (pointer, size);
}
template <class R, class P1, class P2, class P3, class A>
bool asio_handler_is_continuation(
AbstractHandler <R (P1, P2, P3), A>* handler)
{
return handler->is_continuation();
}
template <typename Function, class R, class P1, class P2, class P3, class A>
void asio_handler_invoke (BEAST_MOVE_ARG(Function) function,
AbstractHandler <R (P1, P2, P3), A>* handler)
{
handler->invoke (BEAST_MOVE_CAST(Function)(function));
}
//------------------------------------------------------------------------------
// arity 4
template <class R, class P1, class P2, class P3, class P4, class A>
struct AbstractHandler <R (P1, P2, P3, P4), A>
{
typedef R result_type;
struct Call : detail::AbstractHandlerCallBase
{ virtual R operator() (P1, P2, P3, P4) = 0; };
template <typename H>
struct CallType : public Call
{
typedef typename A:: template rebind <CallType <H> >::other Allocator;
CallType (BEAST_MOVE_ARG(H) h, A a = A ())
: m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a)
{ }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4)
{ return (m_h)(p1, p2, p3, p4); }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4) const
{ return (m_h)(p1, p2, p3, p4); }
void* allocate (std::size_t size)
{ return boost_asio_handler_alloc_helpers::allocate(size, m_h); }
void deallocate (void* pointer, std::size_t size)
{ boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); }
bool is_continuation ()
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
{ return boost_asio_handler_cont_helpers::is_continuation(m_h); }
#else
{ return false; }
#endif
void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked)
{ boost_asio_handler_invoke_helpers::invoke <
typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); }
private:
H m_h;
Allocator m_alloc;
};
template <typename H>
AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ())
: m_call (new (
typename A:: template rebind <CallType <H> >::other (a)
.allocate (1)) CallType <H> (BEAST_MOVE_CAST(H)(h), a))
{ }
R operator() (P1 p1, P2 p2, P3 p3, P4 p4)
{ return (*m_call)(p1, p2, p3, p4); }
R operator() (P1 p1, P2 p2, P3 p3, P4 p4) const
{ return (*m_call)(p1, p2, p3, p4); }
void* allocate (std::size_t size) const { return m_call->allocate(size); }
void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); }
bool is_continuation () const { return m_call->is_continuation(); }
template <typename Function>
void invoke (Function& function) const
{
m_call->invoke(function);
}
template <typename Function>
void invoke (Function const& function) const
{
m_call->invoke(function);
}
private:
SharedPtr <Call> m_call;
};
template <class R, class P1, class P2, class P3, class P4, class A>
void* asio_handler_allocate (std::size_t size,
AbstractHandler <R (P1, P2, P3, P4), A>* handler)
{
return handler->allocate (size);
}
template <class R, class P1, class P2, class P3, class P4, class A>
void asio_handler_deallocate (void* pointer, std::size_t size,
AbstractHandler <R (P1, P2, P3, P4), A>* handler)
{
handler->deallocate (pointer, size);
}
template <class R, class P1, class P2, class P3, class P4, class A>
bool asio_handler_is_continuation(
AbstractHandler <R (P1, P2, P3, P4), A>* handler)
{
return handler->is_continuation();
}
template <typename Function, class R, class P1, class P2, class P3, class P4, class A>
void asio_handler_invoke (BEAST_MOVE_ARG(Function) function,
AbstractHandler <R (P1, P2, P3, P4), A>* handler)
{
handler->invoke (BEAST_MOVE_CAST(Function)(function));
}
//------------------------------------------------------------------------------
// arity 5
template <class R, class P1, class P2, class P3, class P4, class P5, class A>
struct AbstractHandler <R (P1, P2, P3, P4, P5), A>
{
typedef R result_type;
struct Call : detail::AbstractHandlerCallBase
{ virtual R operator() (P1, P2, P3, P4, P5) = 0; };
template <typename H>
struct CallType : public Call
{
typedef typename A:: template rebind <CallType <H> >::other Allocator;
CallType (BEAST_MOVE_ARG(H) h, A a = A ())
: m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a)
{ }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
{ return (m_h)(p1, p2, p3, p4, p5); }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const
{ return (m_h)(p1, p2, p3, p4, p5); }
void* allocate (std::size_t size)
{ return boost_asio_handler_alloc_helpers::allocate(size, m_h); }
void deallocate (void* pointer, std::size_t size)
{ boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); }
bool is_continuation ()
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
{ return boost_asio_handler_cont_helpers::is_continuation(m_h); }
#else
{ return false; }
#endif
void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked)
{ boost_asio_handler_invoke_helpers::invoke <
typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); }
private:
H m_h;
Allocator m_alloc;
};
template <typename H>
AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ())
: m_call (new (
typename A:: template rebind <CallType <H> >::other (a)
.allocate (1)) CallType <H> (BEAST_MOVE_CAST(H)(h), a))
{ }
R operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
{ return (*m_call)(p1, p2, p3, p4, p5); }
R operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const
{ return (*m_call)(p1, p2, p3, p4, p5); }
void* allocate (std::size_t size) const { return m_call->allocate(size); }
void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); }
bool is_continuation () const { return m_call->is_continuation(); }
template <typename Function>
void invoke (Function& function) const
{
m_call->invoke(function);
}
template <typename Function>
void invoke (Function const& function) const
{
m_call->invoke(function);
}
private:
SharedPtr <Call> m_call;
};
template <class R, class P1, class P2, class P3, class P4, class P5, class A>
void* asio_handler_allocate (std::size_t size,
AbstractHandler <R (P1, P2, P3, P4, P5), A>* handler)
{
return handler->allocate (size);
}
template <class R, class P1, class P2, class P3, class P4, class P5, class A>
void asio_handler_deallocate (void* pointer, std::size_t size,
AbstractHandler <R (P1, P2, P3, P4, P5), A>* handler)
{
handler->deallocate (pointer, size);
}
template <class R, class P1, class P2, class P3, class P4, class P5, class A>
bool asio_handler_is_continuation(
AbstractHandler <R (P1, P2, P3, P4, P5), A>* handler)
{
return handler->is_continuation();
}
template <typename Function, class R, class P1, class P2, class P3, class P4, class P5, class A>
void asio_handler_invoke (BEAST_MOVE_ARG(Function) function,
AbstractHandler <R (P1, P2, P3, P4, P5), A>* handler)
{
handler->invoke (BEAST_MOVE_CAST(Function)(function));
}
}
#endif

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
#define BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
namespace beast {
namespace asio {
/** Mix-in to track when all pending I/O is complete.
Derived classes must be callable with this signature:
void asyncHandlersComplete()
@@ -80,4 +83,7 @@ private:
Atomic <int> m_pending;
};
}
}
#endif

View File

@@ -1,98 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_ASYNC_COMPOSEDASYNCOPERATION_H_INCLUDED
#define BEAST_ASIO_ASYNC_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.
*/
explicit ComposedAsyncOperation (SharedHandlerPtr const& ptr)
: 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 <Handler>::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 () const
{
delete this;
}
private:
SharedHandlerPtr const m_ptr;
};
#endif

View File

@@ -1,47 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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);
}

View File

@@ -1,108 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_ASYNC_SHAREDHANDLER_H_INCLUDED
#define BEAST_ASIO_ASYNC_SHAREDHANDLER_H_INCLUDED
template <typename T>
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 SharedFunction <void(void),
SharedHandlerAllocator <char> > invoked_type;
SharedHandler () noexcept { }
public:
// For asio::async_result<>
typedef void result_type;
typedef SharedPtr <SharedHandler> Ptr;
virtual void operator() ();
virtual void operator() (error_code const&);
virtual void operator() (error_code const&, std::size_t);
template <typename Function>
void invoke (BEAST_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;
static void pure_virtual_called (char const* fileName, int lineNumber);
private:
template <typename Function>
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*);
};
//--------------------------------------------------------------------------
//
// Context execution guarantees
//
template <class Function>
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

View File

@@ -1,123 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_ASYNC_SHAREDHANDLERALLOCATOR_H_INCLUDED
#define BEAST_ASIO_ASYNC_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 std::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 <typename T>
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 <typename U>
SharedHandlerAllocator (SharedHandlerAllocator <U> const& other)
: m_ptr (other.m_ptr)
{
}
template <typename U>
struct rebind
{
typedef SharedHandlerAllocator <U> 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 <pointer> (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 <size_type>::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 <typename>
friend struct SharedHandlerAllocator;
friend class SharedHandler;
SharedHandlerPtr m_ptr;
};
//------------------------------------------------------------------------------
template <typename Function>
void SharedHandler::invoke (BEAST_MOVE_ARG(Function) f)
{
// The allocator will hold a reference to the SharedHandler
// so that we can safely destroy the function object.
invoked_type invoked (f,SharedHandlerAllocator <char> (this));
invoke (invoked);
}
#endif

View File

@@ -1,326 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_ASYNC_SHAREDHANDLERPTR_H_INCLUDED
#define BEAST_ASIO_ASYNC_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 ()
{
}
/** 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)
: m_ptr (other.m_ptr)
{
}
/** Assign a reference from an existing container. */
inline SharedHandlerPtr& operator= (SharedHandlerPtr const& other)
{
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)
: 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)
{
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
{
return m_ptr == nullptr;
}
/** Returns true if the handler is not a null handler. */
inline bool isNotNull () const
{
return m_ptr != nullptr;
}
/** Dereference the container.
This returns a reference to the underlying SharedHandler object.
*/
inline SharedHandler& operator* () const
{
return *m_ptr;
}
/** SharedHandler member access.
This lets you call functions directly on the SharedHandler.
*/
inline SharedHandler* operator-> () const
{
return m_ptr.get ();
}
/** Retrieve the SharedHandler as a Context.
This can be used for invoking functions in the context:
@code
template <Function>
void callOnHandler (Function f, SharedHandlerPtr ptr)
{
boost::asio_handler_invoke (f, ptr.get ());
}
@endcode
*/
inline SharedHandler* get () const
{
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 <typename Function>
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 <class Function>
void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandlerPtr* ptr)
{
boost_asio_handler_invoke_helpers::
invoke <Function, SharedHandler>
(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 <SharedHandler> (size, *ptr->get ());
}
inline void asio_handler_deallocate (void* p, std::size_t size, SharedHandlerPtr* ptr)
{
boost_asio_handler_alloc_helpers::
deallocate <SharedHandler> (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 <SharedHandler> (*ptr->get ());
#else
return false;
#endif
}
//--------------------------------------------------------------------------
//
// Helpers
//
//--------------------------------------------------------------------------
// void(error_code)
template <typename Handler>
SharedHandlerPtr newErrorHandler (
BOOST_ASIO_MOVE_ARG(Handler) handler)
{
return newSharedHandlerContainer <ErrorSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(Handler)(handler));
}
// void(error_code, size_t)
template <typename Handler>
SharedHandlerPtr newTransferHandler (
BOOST_ASIO_MOVE_ARG(Handler) handler)
{
return newSharedHandlerContainer <TransferSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(Handler)(handler));
}
//--------------------------------------------------------------------------
// CompletionHandler
//
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/CompletionHandler.html
//
template <typename CompletionHandler>
SharedHandlerPtr newCompletionHandler (
BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
{
return newSharedHandlerContainer <PostSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
}
// AcceptHandler
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AcceptHandler.html
//
template <typename AcceptHandler>
SharedHandlerPtr newAcceptHandler (
BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
{
return newSharedHandlerContainer <ErrorSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
}
// ConnectHandler
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ConnectHandler.html
//
template <typename ConnectHandler>
SharedHandlerPtr newConnectHandler (
BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
{
return newSharedHandlerContainer <ErrorSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
}
// ShutdownHandler
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ShutdownHandler.html
//
template <typename ShutdownHandler>
SharedHandlerPtr newShutdownHandler(
BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
{
return newSharedHandlerContainer <ErrorSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
}
// HandshakeHandler
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/HandshakeHandler.html
//
template <typename HandshakeHandler>
SharedHandlerPtr newHandshakeHandler(
BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
{
return newSharedHandlerContainer <ErrorSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
}
// ReadHandler
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ReadHandler.html
//
template <typename ReadHandler>
SharedHandlerPtr newReadHandler(
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
return newSharedHandlerContainer <TransferSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
}
// WriteHandler
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/WriteHandler.html
//
template <typename WriteHandler>
SharedHandlerPtr newWriteHandler(
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
return newSharedHandlerContainer <TransferSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
}
// BufferedHandshakeHandler
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/BufferedHandshakeHandler.html
//
template <typename BufferedHandshakeHandler>
SharedHandlerPtr newBufferedHandshakeHandler(
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
{
return newSharedHandlerContainer <TransferSharedHandlerType> (
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
}
#endif

View File

@@ -1,211 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_ASYNC_SHAREDHANDLERTYPE_H_INCLUDED
#define BEAST_ASIO_ASYNC_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 <typename Handler>
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_type, Handler> (invoked, m_handler);
}
void* allocate (std::size_t size)
{
return boost_asio_handler_alloc_helpers::
allocate <Handler> (size, m_handler);
}
void deallocate (void* p, std::size_t size)
{
boost_asio_handler_alloc_helpers::
deallocate <Handler> (p, size, m_handler);
}
bool is_continuation ()
{
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
return boost_asio_handler_cont_helpers::
is_continuation <Handler> (m_handler);
#else
return false;
#endif
}
// Called by SharedObject 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 () const
{
Handler local (BOOST_ASIO_MOVE_CAST(Handler)(m_handler));
std::size_t const size (m_size);
SharedHandler* const shared (
const_cast <SharedHandler*> (
static_cast <SharedHandler const*>(this)));
shared->~SharedHandler ();
boost_asio_handler_alloc_helpers::
deallocate <Handler> (shared, size, local);
}
protected:
std::size_t const m_size;
Handler mutable m_handler;
};
//--------------------------------------------------------------------------
//
// A SharedHandlerType for this signature:
// void(void)
//
template <typename Handler>
class PostSharedHandlerType : public SharedHandlerType <Handler>
{
public:
PostSharedHandlerType (std::size_t size,
BOOST_ASIO_MOVE_ARG(Handler) handler)
: SharedHandlerType <Handler> (size,
BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
}
protected:
void operator() ()
{
this->m_handler ();
}
};
//--------------------------------------------------------------------------
//
// A SharedHandlerType for this signature:
// void(error_code)
//
template <typename Handler>
class ErrorSharedHandlerType : public SharedHandlerType <Handler>
{
public:
ErrorSharedHandlerType (std::size_t size,
BOOST_ASIO_MOVE_ARG(Handler) handler)
: SharedHandlerType <Handler> (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 <typename Handler>
class TransferSharedHandlerType : public SharedHandlerType <Handler>
{
public:
TransferSharedHandlerType (std::size_t size,
BOOST_ASIO_MOVE_ARG(Handler) handler)
: SharedHandlerType <Handler> (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 <SharedHandler>
{
};
template <>
class ErrorSharedHandlerType <SharedHandler>
{
};
template <>
class TransferSharedHandlerType <SharedHandler>
{
};
#endif
//--------------------------------------------------------------------------
/** Construct a wrapped handler using the context's allocation hooks.
*/
template <template <typename> class Container, typename Handler>
Container <Handler>* newSharedHandlerContainer (BOOST_ASIO_MOVE_ARG(Handler) handler)
{
typedef Container <Handler> ContainerType;
std::size_t const size (sizeof (ContainerType));
Handler local (BOOST_ASIO_MOVE_CAST(Handler)(handler));
void* const p (boost_asio_handler_alloc_helpers::
allocate <Handler> (size, local));
return new (p) ContainerType (size, BOOST_ASIO_MOVE_CAST(Handler)(local));
}
#endif

View File

@@ -1,209 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_WRAPHANDLER_H_INCLUDED
#define BEAST_ASIO_WRAPHANDLER_H_INCLUDED
namespace beast {
namespace detail {
// Wrapper returned by wrapHandler, calls the Handler in the given Context
//
template <typename Handler, typename Context>
class WrappedHandler
{
public:
typedef void result_type; // for result_of
WrappedHandler (Handler& handler, Context const& context)
: m_handler (handler)
, m_context (context)
{
}
WrappedHandler (Handler const& handler, Context const& context)
: m_handler (handler)
, m_context (context)
{
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
WrappedHandler (WrappedHandler const& other)
: m_handler (other.m_handler)
, m_context (other.m_context)
{
}
WrappedHandler (BEAST_MOVE_ARG(WrappedHandler) other)
: m_handler (BEAST_MOVE_CAST(Handler)(other.m_handler))
, m_context (BEAST_MOVE_CAST(Context)(other.m_context))
{
}
#endif
Handler& handler()
{ return m_handler; }
Handler const& handler() const
{ return m_handler; }
Context& context()
{ return m_context; }
Context const& context() const
{ return m_context; }
void operator() ()
{ m_handler(); }
void operator() () const
{ m_handler(); }
template <class P1>
void operator() (P1 const& p1)
{ m_handler(p1); }
template <class P1>
void operator() (P1 const& p1) const
{ m_handler(p1); }
template <class P1, class P2>
void operator() (P1 const& p1, P2 const& p2)
{ m_handler(p1, p2); }
template <class P1, class P2>
void operator() (P1 const& p1, P2 const& p2) const
{ m_handler(p1, p2); }
template <class P1, class P2, class P3>
void operator() (P1 const& p1, P2 const& p2, P3 const& p3)
{ m_handler(p1, p2, p3); }
template <class P1, class P2, class P3>
void operator() (P1 const& p1, P2 const& p2, P3 const& p3) const
{ m_handler(p1, p2, p3); }
template <class P1, class P2, class P3, class P4>
void operator()
(P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4)
{ m_handler(p1, p2, p3, p4); }
template <class P1, class P2, class P3, class P4>
void operator()
(P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) const
{ m_handler(p1, p2, p3, p4); }
template <class P1, class P2, class P3,
class P4, class P5>
void operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5)
{ m_handler(p1, p2, p3, p4, p5); }
template <class P1, class P2, class P3,
class P4, class P5>
void operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5) const
{ m_handler(p1, p2, p3, p4, p5); }
template <class P1, class P2, class P3,
class P4, class P5, class P6>
void operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5, P6 const& p6)
{ m_handler(p1, p2, p3, p4, p5, p6); }
template <class P1, class P2, class P3,
class P4, class P5, class P6>
void operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5, P6 const& p6) const
{ m_handler(p1, p2, p3, p4, p5, p6); }
private:
Handler m_handler;
Context m_context;
};
//------------------------------------------------------------------------------
template <typename Handler, typename Context>
void* asio_handler_allocate (std::size_t size,
WrappedHandler <Handler, Context>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->context());
}
template <typename Handler, typename Context>
void asio_handler_deallocate (void* pointer, std::size_t size,
WrappedHandler <Handler, Context>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->context());
}
template <typename Handler, typename Context>
bool asio_handler_is_continuation(
WrappedHandler <Handler, Context>* this_handler)
{
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler());
#else
return false;
#endif
}
template <typename Function, typename Handler, typename Context>
void asio_handler_invoke (Function& function,
WrappedHandler <Handler, Context>* handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, handler->context());
}
template <typename Function, typename Handler, typename Context>
void asio_handler_invoke (Function const& function,
WrappedHandler <Handler, Context>* handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, handler->context());
}
}
//------------------------------------------------------------------------------
/** Returns a handler that calls Handler using Context hooks.
This is useful when implementing composed asynchronous operations that
need to call their own intermediate handlers before issuing the final
completion to the original handler.
*/
template <typename Handler, typename Context>
detail::WrappedHandler <Handler, Context>
wrapHandler (
BEAST_MOVE_ARG(Handler) handler,
BEAST_MOVE_ARG(Context) context)
{
return detail::WrappedHandler <Handler, Context> (
BEAST_MOVE_CAST(Handler)(handler),
BEAST_MOVE_CAST(Context)(context));
}
}
#endif

View File

@@ -1,135 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_BUFFERSTYPE_H_INCLUDED
#define BEAST_ASIO_BUFFERSTYPE_H_INCLUDED
/** Storage for a BufferSequence.
Meets these requirements:
BufferSequence
ConstBufferSequence (when Buffer is mutable_buffer)
MutableBufferSequence (when Buffer is const_buffer)
*/
template <class Buffer>
class BuffersType
{
public:
typedef Buffer value_type;
typedef std::vector <Buffer> container_type;
typedef typename container_type::const_iterator const_iterator;
/** Construct a null buffer.
This is the equivalent of @ref asio::null_buffers.
*/
BuffersType ()
: m_size (0)
{
}
/** Construct from a container.
Ownership of the container is transferred, the caller's
value becomes undefined, but valid.
*/
explicit BuffersType (container_type& container)
: m_size (0)
{
m_buffers.swap (container);
for (typename container_type::const_iterator iter (m_buffers.begin ());
iter != m_buffers.end (); ++iter)
//m_size += iter->size ();
m_size += boost::asio::buffer_size (*iter);
}
/** Construct a BuffersType from an existing BufferSequence.
@see assign
*/
template <class BufferSequence>
BuffersType (BufferSequence const& buffers)
{
assign (buffers);
}
/** Assign a BuffersType from an existing BufferSequence.
@see assign
*/
template <class BufferSequence>
BuffersType <Buffer>& operator= (BufferSequence const& buffers)
{
return assign (buffers);
}
/** Assign a BuffersType 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 <class BufferSequence>
BuffersType <Buffer>& assign (BufferSequence const& buffers)
{
m_size = 0;
m_buffers.clear ();
m_buffers.reserve (std::distance (buffers.begin (), buffers.end ()));
for (typename BufferSequence::const_iterator iter (
buffers.begin ()); iter != buffers.end(); ++ iter)
{
//m_size += iter->size ();
m_size += boost::asio::buffer_size (*iter);
m_buffers.push_back (*iter);
}
return *this;
}
/** Determine the total size of all buffers.
This is faster than calling boost::asio::buffer_size.
*/
std::size_t size () const noexcept
{
return m_size;
}
const_iterator begin () const noexcept
{
return m_buffers.begin ();
}
const_iterator end () const noexcept
{
return m_buffers.end ();
}
private:
std::size_t m_size;
std::vector <Buffer> 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 */
typedef BuffersType <ConstBuffer> ConstBuffers;
/** Meets the requirements of MutableBufferSequence */
typedef BuffersType <MutableBuffer> MutableBuffers;
#endif

View File

@@ -20,6 +20,11 @@
#ifndef BEAST_ASIO_BASICS_FIXEDINPUTBUFFER_H_INCLUDED
#define BEAST_ASIO_BASICS_FIXEDINPUTBUFFER_H_INCLUDED
#include "../../../beast/asio/buffer_sequence.h"
namespace beast {
namespace asio {
/** Represents a small, fixed size buffer.
This provides a convenient interface for doing a bytewise
verification/reject test on a handshake protocol.
@@ -164,7 +169,7 @@ protected:
template <typename ConstBufferSequence, typename Storage>
SizedCtorParams (ConstBufferSequence const& buffers, Storage& storage)
{
MutableBuffer buffer (boost::asio::buffer (storage));
boost::asio::mutable_buffer buffer (boost::asio::buffer (storage));
data = boost::asio::buffer_cast <uint8 const*> (buffer);
bytes = boost::asio::buffer_copy (buffer, buffers);
}
@@ -187,7 +192,10 @@ public:
private:
boost::array <uint8, Bytes> m_storage;
MutableBuffer m_buffer;
boost::asio::mutable_buffer m_buffer;
};
}
}
#endif

View File

@@ -17,6 +17,9 @@
*/
//==============================================================================
namespace beast {
namespace asio {
PeerRole::PeerRole (role_t role)
: m_role (role)
{
@@ -35,10 +38,13 @@ bool PeerRole::operator== (role_t role) const noexcept
}
#if 0
PeerRole::operator Socket::handshake_type () const noexcept
PeerRole::operator abstract_socket::handshake_type () const noexcept
{
if (m_role == server)
return Socket::server;
return Socket::client;
return abstract_socket::server;
return abstract_socket::client;
}
#endif
}
}

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_BASICS_PEERROLE_H_INCLUDED
#define BEAST_ASIO_BASICS_PEERROLE_H_INCLUDED
namespace beast {
namespace asio {
/** Identifies if the peer is a client or a server. */
struct PeerRole
{
@@ -37,4 +40,7 @@ private:
role_t m_role;
};
}
}
#endif

View File

@@ -17,6 +17,9 @@
*/
//==============================================================================
namespace beast {
namespace asio {
SSLContext::SSLContext (ContextType& context)
: m_context (context)
{
@@ -26,3 +29,5 @@ SSLContext::~SSLContext ()
{
}
}
}

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
#define BEAST_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
namespace beast {
namespace asio {
/** Simple base class for passing a context around.
This lets derived classes hide their implementation from the headers.
*/
@@ -58,4 +61,7 @@ protected:
ContextType& m_context;
};
}
}
#endif

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_SHAREDARG_H_INCLUDED
#define BEAST_ASIO_SHAREDARG_H_INCLUDED
namespace beast {
namespace asio {
/** A container that turns T into a SharedObject.
We use this to manage the lifetime of objects passed to handlers.
*/
@@ -158,4 +161,7 @@ private:
SharedPtr <Arg> m_arg;
};
}
}
#endif

View File

@@ -23,18 +23,11 @@
#include "beast_asio.h"
namespace beast {
# include "../../beast/http/impl/http-parser/http_parser.h"
#include "async/SharedHandler.cpp"
# include "../../beast/http/impl/http_parser.h"
#include "basics/PeerRole.cpp"
#include "basics/SSLContext.cpp"
#include "sockets/SocketBase.cpp"
#include "sockets/Socket.cpp"
#include "protocol/HandshakeDetectLogicPROXY.cpp"
# include "http/HTTPParserImpl.h"
@@ -58,8 +51,6 @@ namespace beast {
#include "system/BoostUnitTests.cpp"
}
#include "http/HTTPParser.cpp"
#include "http/HTTPRequestParser.cpp"
#include "http/HTTPResponseParser.cpp"

View File

@@ -43,45 +43,19 @@
// This module requires boost and possibly OpenSSL
#include "system/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
#include "../../beast/Asio.h"
#include "../../beast/MPL.h"
#include "../../beast/Utility.h"
#include "../../beast/HTTP.h"
#include "async/AbstractHandler.h"
#include "async/WrapHandler.h"
namespace beast {
#include "../../beast/asio/IPAddressConversion.h"
// Order matters
# include "async/SharedHandler.h"
# include "async/SharedHandlerType.h"
# include "async/SharedHandlerPtr.h"
# include "async/ComposedAsyncOperation.h"
#include "async/SharedHandlerAllocator.h"
#include "async/AsyncObject.h"
# include "basics/BuffersType.h"
#include "basics/FixedInputBuffer.h"
#include "basics/PeerRole.h"
#include "basics/SSLContext.h"
#include "basics/SharedArg.h"
# include "sockets/SocketBase.h"
# include "sockets/Socket.h"
# include "sockets/SocketWrapper.h"
#include "sockets/SocketWrapperStrand.h"
# include "http/HTTPVersion.h"
# include "http/HTTPField.h"
# include "http/HTTPHeaders.h"
@@ -89,16 +63,12 @@ namespace beast {
# include "http/HTTPRequest.h"
# include "http/HTTPResponse.h"
}
# include "http/HTTPParser.h"
#include "http/HTTPRequestParser.h"
#include "http/HTTPResponseParser.h"
#include "http/HTTPClientType.h"
namespace beast {
# include "protocol/InputParser.h"
# include "protocol/HandshakeDetectLogic.h"
#include "protocol/HandshakeDetectLogicPROXY.h"
@@ -120,7 +90,5 @@ namespace beast {
#include "tests/TestPeerDetailsTcp.h"
#include "tests/PeerTest.h"
}
#endif

View File

@@ -17,6 +17,12 @@
*/
//==============================================================================
#include "../../../beast/asio/wrap_handler.h"
#include "../../../beast/asio/placeholders.h"
namespace beast {
namespace asio {
class HTTPClientType : public HTTPClientBase, public Uncopyable
{
public:
@@ -69,7 +75,7 @@ public:
}
void async_get (boost::asio::io_service& io_service, URL const& url,
AbstractHandler <void (result_type)> handler)
asio::shared_handler <void (result_type)> handler)
{
new Session (*this, io_service, url,
handler, m_timeoutSeconds, m_messageLimitBytes, m_bufferSize);
@@ -150,7 +156,6 @@ public:
class Session
: public SharedObject
, public AsyncObject <Session>
, public List <Session>::Node
{
public:
@@ -173,7 +178,7 @@ public:
boost::asio::deadline_timer m_timer;
resolver m_resolver;
socket m_socket;
AbstractHandler <void (result_type)> m_handler;
asio::shared_handler <void (result_type)> m_handler;
URL m_url;
boost::asio::ssl::context m_context;
@@ -184,7 +189,7 @@ public:
String m_get_string;
WaitableEvent m_done;
ScopedPointer <Socket> m_stream;
ScopedPointer <abstract_socket> m_stream;
struct State
{
@@ -204,7 +209,7 @@ public:
Session (HTTPClientType& owner,
boost::asio::io_service& io_service,
URL const& url,
AbstractHandler <void (result_type)> const& handler,
asio::shared_handler <void (result_type)> const& handler,
double timeoutSeconds,
std::size_t messageLimitBytes,
std::size_t bufferSize)
@@ -238,16 +243,14 @@ public:
boost::posix_time::milliseconds (
long (timeoutSeconds * 1000)));
m_timer.async_wait (m_strand.wrap (wrapHandler (
boost::bind (&Session::handle_timer, Ptr(this),
boost::asio::placeholders::error,
CompletionCounter(this)), m_handler)));
m_timer.async_wait (m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_timer, Ptr(this),
asio::placeholders::error), m_handler)));
}
// Start the operation on an io_service thread
io_service.dispatch (m_strand.wrap (wrapHandler (
boost::bind (&Session::handle_start, Ptr(this),
CompletionCounter(this)), m_handler)));
io_service.dispatch (m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_start, Ptr(this)), m_handler)));
}
~Session ()
@@ -258,8 +261,8 @@ public:
result = *state;
}
m_io_service.wrap (m_handler) (std::make_pair (
result.error, result.response));
m_io_service.post (bind_handler (m_handler,
std::make_pair (result.error, result.response)));
m_owner.remove (*this);
}
@@ -313,10 +316,9 @@ public:
m_buffer.getData (), m_buffer.getSize ());
m_stream->async_read_some (buf, m_strand.wrap (
wrapHandler (boost::bind (&Session::handle_read,
Ptr(this), boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
CompletionCounter(this)), m_handler)));
asio::wrap_handler (std::bind (&Session::handle_read,
Ptr(this), asio::placeholders::error,
asio::placeholders::bytes_transferred), m_handler)));
}
//----------------------------------------------------------------------
@@ -324,25 +326,19 @@ public:
// Completion handlers
//
// Called when there are no more pending i/o completions
void asyncHandlersComplete()
{
}
// Called when the operation starts
void handle_start (CompletionCounter)
void handle_start ()
{
query q (queryFromURL <query> (m_url));
m_resolver.async_resolve (q, m_strand.wrap (
wrapHandler (boost::bind (&Session::handle_resolve,
Ptr(this), boost::asio::placeholders::error,
boost::asio::placeholders::iterator,
CompletionCounter(this)), m_handler)));
asio::wrap_handler (std::bind (&Session::handle_resolve,
Ptr(this), asio::placeholders::error,
asio::placeholders::iterator), m_handler)));
}
// Called when the timer completes
void handle_timer (error_code ec, CompletionCounter)
void handle_timer (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
@@ -358,7 +354,7 @@ public:
}
// Called when the resolver completes
void handle_resolve (error_code ec, iterator iter, CompletionCounter)
void handle_resolve (error_code ec, iterator iter)
{
if (ec == boost::asio::error::operation_aborted)
return;
@@ -371,13 +367,12 @@ public:
resolver_entry const entry (*iter);
m_socket.async_connect (entry.endpoint (), m_strand.wrap (
wrapHandler (boost::bind (&Session::handle_connect,
Ptr(this), boost::asio::placeholders::error,
CompletionCounter(this)), m_handler)));
asio::wrap_handler (std::bind (&Session::handle_connect,
Ptr(this), asio::placeholders::error), m_handler)));
}
// Called when the connection attempt completes
void handle_connect (error_code ec, CompletionCounter)
void handle_connect (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
@@ -391,25 +386,24 @@ public:
if (m_url.scheme () == "https")
{
typedef boost::asio::ssl::stream <socket&> ssl_stream;
m_stream = new SocketWrapper <ssl_stream> (m_socket, m_context);
m_stream = new socket_wrapper <ssl_stream> (m_socket, m_context);
/*
m_stream->set_verify_mode (
boost::asio::ssl::verify_peer |
boost::asio::ssl::verify_fail_if_no_peer_cert);
*/
m_stream->async_handshake (Socket::client, m_strand.wrap (
wrapHandler (boost::bind (&Session::handle_handshake,
Ptr(this), boost::asio::placeholders::error,
CompletionCounter(this)), m_handler)));
m_stream->async_handshake (abstract_socket::client, m_strand.wrap (
asio::wrap_handler (std::bind (&Session::handle_handshake,
Ptr(this), asio::placeholders::error), m_handler)));
return;
}
m_stream = new SocketWrapper <socket&> (m_socket);
handle_handshake (ec, CompletionCounter(this));
m_stream = new socket_wrapper <socket&> (m_socket);
handle_handshake (ec);
}
// Called when the SSL handshake completes
void handle_handshake (error_code ec, CompletionCounter)
void handle_handshake (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
@@ -427,17 +421,16 @@ public:
"Connection: close\r\n\r\n";
boost::asio::async_write (*m_stream, stringBuffer (
m_get_string), m_strand.wrap (wrapHandler (
boost::bind (&Session::handle_write, Ptr(this),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
CompletionCounter(this)), m_handler)));
m_get_string), m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_write, Ptr(this),
asio::placeholders::error,
asio::placeholders::bytes_transferred), m_handler)));
async_read_some ();
}
// Called when the write operation completes
void handle_write (error_code ec, std::size_t, CompletionCounter)
void handle_write (error_code ec, std::size_t)
{
if (ec == boost::asio::error::operation_aborted)
return;
@@ -453,7 +446,7 @@ public:
}
void handle_read (error_code ec,
std::size_t bytes_transferred, CompletionCounter)
std::size_t bytes_transferred)
{
if (ec == boost::asio::error::operation_aborted)
return;
@@ -499,14 +492,13 @@ public:
{
if (m_stream->needs_handshake ())
{
m_stream->async_shutdown (m_strand.wrap (wrapHandler (
boost::bind (&Session::handle_shutdown, Ptr(this),
boost::asio::placeholders::error,
CompletionCounter(this)), m_handler)));
m_stream->async_shutdown (m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_shutdown,
Ptr(this), asio::placeholders::error), m_handler)));
}
else
{
handle_shutdown (error_code (), CompletionCounter(this));
handle_shutdown (error_code ());
}
return;
}
@@ -514,7 +506,7 @@ public:
async_read_some ();
}
void handle_shutdown (error_code ec, CompletionCounter)
void handle_shutdown (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
@@ -692,4 +684,5 @@ public:
static HTTPClientTests httpClientTests;
}
}

View File

@@ -20,9 +20,12 @@
#ifndef BEAST_ASIO_HTTPCLIENTTYPE_H_INCLUDED
#define BEAST_ASIO_HTTPCLIENTTYPE_H_INCLUDED
#include "../../../beast/asio/shared_handler.h"
#include <utility>
namespace beast {
namespace asio {
class HTTPClientBase
{
@@ -49,17 +52,8 @@ public:
Handler will be called with this signature:
void (result_type)
*/
template <typename Handler>
void async_get (boost::asio::io_service& io_service,
URL const& url, BEAST_MOVE_ARG(Handler) handler)
{
async_get (io_service, url,
AbstractHandler <void (result_type)> (
BEAST_MOVE_CAST(Handler)(handler)));
}
virtual void async_get (boost::asio::io_service& io_service,
URL const& url, AbstractHandler <void (result_type)> handler) = 0;
URL const& url, asio::shared_handler <void (result_type)> handler) = 0;
/** Cancel all pending asynchronous operations. */
virtual void cancel() = 0;
@@ -68,6 +62,7 @@ public:
virtual void wait() = 0;
};
}
}
#endif

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace beast {
HTTPField::HTTPField ()
{
}
@@ -49,3 +51,5 @@ String HTTPField::value () const
{
return m_value;
}
}

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_HTTPFIELD_H_INCLUDED
#define BEAST_ASIO_HTTPFIELD_H_INCLUDED
namespace beast {
/** A single header.
The header is a field/value pair.
Time complexity of copies is constant.
@@ -39,4 +41,6 @@ private:
String m_value;
};
}
#endif

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace beast {
HTTPHeaders::HTTPHeaders ()
{
}
@@ -84,3 +86,4 @@ String HTTPHeaders::toString () const
return s;
}
}

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_HTTPHEADERS_H_INCLUDED
#define BEAST_ASIO_HTTPHEADERS_H_INCLUDED
namespace beast {
/** A set of HTTP headers. */
class HTTPHeaders
{
@@ -68,4 +70,6 @@ private:
StringPairArray m_fields;
};
}
#endif

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace beast {
HTTPMessage::HTTPMessage (HTTPVersion const& version_,
StringPairArray& fields,
DynamicBuffer& body)
@@ -48,3 +50,5 @@ String HTTPMessage::toString () const
s << m_headers.toString ();
return s;
}
}

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_HTTPMESSAGE_H_INCLUDED
#define BEAST_ASIO_HTTPMESSAGE_H_INCLUDED
namespace beast {
/** A complete HTTP message.
This provides the information common to all HTTP messages, including
@@ -60,4 +62,6 @@ private:
DynamicBuffer m_body;
};
}
#endif

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_HTTPPARSERIMPL_H_INCLUDED
#define BEAST_HTTPPARSERIMPL_H_INCLUDED
namespace beast {
class HTTPParserImpl
{
public:
@@ -266,4 +268,6 @@ private:
DynamicBuffer m_body;
};
}
#endif

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace beast {
HTTPRequest::HTTPRequest (
HTTPVersion const& version_,
StringPairArray& fields,
@@ -40,3 +42,4 @@ String HTTPRequest::toString () const
return s;
}
}

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_HTTPREQUEST_H_INCLUDED
#define BEAST_ASIO_HTTPREQUEST_H_INCLUDED
namespace beast {
class HTTPRequest : public HTTPMessage
{
public:
@@ -42,4 +44,6 @@ private:
unsigned short m_method;
};
}
#endif

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace beast {
HTTPResponse::HTTPResponse (
HTTPVersion const& version_,
StringPairArray& fields,
@@ -40,3 +42,4 @@ String HTTPResponse::toString () const
return s;
}
}

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_HTTPRESPONSE_H_INCLUDED
#define BEAST_ASIO_HTTPRESPONSE_H_INCLUDED
namespace beast {
class HTTPResponse : public HTTPMessage
{
public:
@@ -42,4 +44,6 @@ private:
unsigned short m_status;
};
}
#endif

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace beast {
HTTPVersion::HTTPVersion ()
: m_major (0)
, m_minor (0)
@@ -91,3 +93,5 @@ bool HTTPVersion::operator<= (HTTPVersion const& rhs) const
return (m_major < rhs.m_major) ||
((m_major == rhs.m_major) && (m_minor <= rhs.m_minor));
}
}

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_HTTPVERSION_H_INCLUDED
#define BEAST_ASIO_HTTPVERSION_H_INCLUDED
namespace beast {
/** The HTTP version. This is the major.minor version number. */
class HTTPVersion
{
@@ -43,4 +45,6 @@ private:
unsigned short m_minor;
};
}
#endif

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGIC_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGIC_H_INCLUDED
namespace beast {
namespace asio {
class HandshakeDetectLogic
{
public:
@@ -138,4 +141,7 @@ private:
Logic m_logic;
};
}
}
#endif

View File

@@ -17,4 +17,8 @@
*/
//==============================================================================
namespace beast {
namespace asio {
}
}

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICPROXY_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICPROXY_H_INCLUDED
namespace beast {
namespace asio {
/** Handshake detector for the PROXY protcol
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
@@ -156,4 +159,7 @@ private:
ProxyInfo m_info;
};
}
}
#endif

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED
namespace beast {
namespace asio {
// Handshake for SSL 2
//
// http://tools.ietf.org/html/rfc5246#appendix-E.2
@@ -105,4 +108,7 @@ public:
}
};
}
}
#endif

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED
namespace beast {
namespace asio {
// Handshake for SSL 3 (Also TLS 1.0 and 1.1)
//
// http://www.ietf.org/rfc/rfc2246.txt
@@ -79,4 +82,7 @@ public:
}
};
}
}
#endif

View File

@@ -20,7 +20,16 @@
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTOR_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTOR_H_INCLUDED
//------------------------------------------------------------------------------
#include "../../../beast/boost/get_pointer.h"
#include "../../../beast/asio/bind_handler.h"
#include "../../../beast/asio/wrap_handler.h"
#include "../../../beast/asio/placeholders.h"
#include "../../../beast/asio/shared_handler.h"
#include <boost/asio/detail/handler_cont_helpers.hpp>
namespace beast {
namespace asio {
/** A wrapper to decode the handshake data on a Stream.
@@ -99,42 +108,35 @@ public:
DetectHandler must have this signature:
void(error_code)
*/
template <typename DetectHandler, typename Allocator>
void async_detect (Stream& stream,
boost::asio::basic_streambuf <Allocator>& buffer,
BOOST_ASIO_MOVE_ARG(DetectHandler) handler)
{
async_detect <Allocator> (stream, buffer, SharedHandlerPtr (
new ErrorSharedHandlerType <DetectHandler> (
BOOST_ASIO_MOVE_CAST(DetectHandler)(handler))));
}
template <typename Allocator>
void async_detect (Stream& stream,
boost::asio::basic_streambuf <Allocator>& buffer,
SharedHandlerPtr handler)
asio::shared_handler <void(error_code)> handler)
{
typedef AsyncOp <Allocator> OpType;
OpType* const op = new AsyncOp <Allocator> (
m_logic, stream, buffer, handler);
stream.get_io_service ().wrap (SharedHandlerPtr (op))
(error_code (), 0);
typedef AsyncOp <Allocator> Op;
auto const op (std::make_shared <Op> (std::ref (m_logic),
std::ref (stream), std::ref (buffer), std::cref (handler)));
//op->start();
stream.get_io_service().post (asio::wrap_handler (std::bind (
&Op::start, op), handler));
}
private:
template <typename Allocator>
struct AsyncOp : ComposedAsyncOperation
class AsyncOp
: public std::enable_shared_from_this <AsyncOp <Allocator>>
{
public:
typedef boost::asio::basic_streambuf <Allocator> BuffersType;
AsyncOp (HandshakeDetectLogicType <Logic>& logic, Stream& stream,
BuffersType& buffer, SharedHandlerPtr const& handler)
: ComposedAsyncOperation (handler)
, m_logic (logic)
BuffersType& buffer, asio::shared_handler <
void(error_code)> const& handler)
: m_logic (logic)
, m_stream (stream)
, m_buffer (buffer)
, m_handler (handler)
, m_running (false)
, m_continuation (false)
{
}
@@ -143,12 +145,19 @@ private:
{
}
void operator() (error_code const& ec_, size_t bytes_transferred)
void start()
{
m_running = true;
async_read_some (error_code(), 0);
}
error_code ec (ec_);
void on_read (error_code ec, size_t bytes_transferred)
{
m_continuation = true;
async_read_some (ec, bytes_transferred);
}
void async_read_some (error_code ec, size_t bytes_transferred)
{
if (! ec)
{
m_buffer.commit (bytes_transferred);
@@ -163,10 +172,14 @@ private:
// If postcondition fails, loop will never end
if (meets_postcondition (available < needed))
{
typename BuffersType::mutable_buffers_type buffers (
typename BuffersType::mutable_buffers_type buffers (
m_buffer.prepare (needed - available));
m_stream.async_read_some (buffers, SharedHandlerPtr (this));
m_stream.async_read_some (buffers, asio::wrap_handler (
std::bind (&AsyncOp <Allocator>::on_read,
this->shared_from_this(), asio::placeholders::error,
asio::placeholders::bytes_transferred),
m_handler, m_continuation));
}
return;
@@ -177,30 +190,30 @@ private:
}
// 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
;
if (m_continuation)
{
m_handler (ec);
return;
}
// Post, otherwise we would call the
// handler from the initiating function.
m_stream.get_io_service ().post (asio::bind_handler (
m_handler, ec));
}
private:
HandshakeDetectLogicType <Logic>& m_logic;
Stream& m_stream;
BuffersType& m_buffer;
SharedHandlerPtr m_handler;
bool m_running;
asio::shared_handler <void(error_code)> m_handler;
bool m_continuation;
};
private:
HandshakeDetectLogicType <Logic> m_logic;
};
}
}
#endif

View File

@@ -20,8 +20,10 @@
#ifndef BEAST_ASIO_HANDSHAKE_INPUTPARSER_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_INPUTPARSER_H_INCLUDED
namespace InputParser
{
namespace beast {
namespace asio {
namespace InputParser {
/** Tri-valued parsing state.
This is convertible to bool which means continue.
@@ -380,8 +382,9 @@ struct Get <IPv4Address>
}
};
//------------------------------------------------------------------------------
}
}
}
#endif

View File

@@ -20,6 +20,12 @@
#ifndef BEAST_ASIO_HANDSHAKE_PREFILLEDREADSTREAM_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_PREFILLEDREADSTREAM_H_INCLUDED
#include "../../../beast/cxx14/type_traits.h" // <type_traits>
#include <utility>
namespace beast {
namespace asio {
/** Front-ends a stream with a provided block of data.
When read operations are performed on this object, bytes will first be
@@ -29,25 +35,25 @@
Write operations are all simply passed through.
*/
template <typename Stream>
template <class Stream>
class PrefilledReadStream : public Uncopyable
{
protected:
typedef boost::system::error_code error_code;
void throw_error (error_code const& ec, char const* fileName, int lineNumber)
static void throw_if (error_code const& ec)
{
Throw (boost::system::system_error (ec), fileName, lineNumber);
throw boost::system::system_error (ec);
}
public:
typedef typename boost::remove_reference <Stream>::type next_layer_type;
typedef std::remove_reference_t <Stream> next_layer_type;
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
/** Single argument constructor for when we are wrapped in something.
arg is passed through to the next layer's constructor.
*/
template <typename Arg>
template <class Arg>
explicit PrefilledReadStream (Arg& arg)
: m_next_layer (arg)
{
@@ -57,7 +63,7 @@ public:
This creates a copy of the data. The argument is passed through
to the constructor of Stream.
*/
template <typename Arg, typename ConstBufferSequence>
template <class Arg, class ConstBufferSequence>
PrefilledReadStream (Arg& arg, ConstBufferSequence const& buffers)
: m_next_layer (arg)
{
@@ -69,15 +75,14 @@ public:
is here is for the case when you can't pass the buffer through the
constructor because there is another object wrapping this stream.
*/
template <typename ConstBufferSequence>
template <class ConstBufferSequence>
void fill (ConstBufferSequence const& buffers)
{
// 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)),
m_buffer.commit (boost::asio::buffer_copy (
m_buffer.prepare (boost::asio::buffer_size (buffers)),
buffers));
}
@@ -109,8 +114,8 @@ public:
void close()
{
error_code ec;
if (close (ec))
throw_error (ec, __FILE__, __LINE__);
close (ec);
throw_if (ec);
}
error_code close (error_code& ec)
@@ -122,18 +127,18 @@ public:
return lowest_layer ().close(ec);
}
template <typename MutableBufferSequence>
template <class MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers)
{
error_code ec;
std::size_t const amount = read_some (buffers, ec);
if (ec)
throw_error (ec, __FILE__, __LINE__);
throw_if (ec);
return amount;
}
template <typename MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec)
template <class MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers,
error_code& ec)
{
if (m_buffer.size () > 0)
{
@@ -146,46 +151,46 @@ public:
return m_next_layer.read_some (buffers, ec);
}
template <typename ConstBufferSequence>
template <class ConstBufferSequence>
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__);
auto const amount (write_some (buffers, ec));
throw_if (ec);
return amount;
}
template <typename ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec)
template <class ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers,
error_code& ec)
{
return m_next_layer.write_some (buffers, ec);
}
template <typename MutableBufferSequence, typename ReadHandler>
template <class MutableBufferSequence, class ReadHandler>
void async_read_some (MutableBufferSequence const& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
ReadHandler&& handler)
{
if (m_buffer.size () > 0)
{
std::size_t const bytes_transferred = boost::asio::buffer_copy (
buffers, m_buffer.data ());
auto 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);
get_io_service ().post (bind_handler (
std::forward <ReadHandler> (handler),
error_code (), bytes_transferred));
return;
}
m_next_layer.async_read_some (buffers,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
std::forward <ReadHandler> (handler));
}
template <typename ConstBufferSequence, typename WriteHandler>
template <class ConstBufferSequence, class WriteHandler>
void async_write_some (ConstBufferSequence const& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
WriteHandler&& handler)
{
m_next_layer.async_write_some (buffers,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
std::forward <WriteHandler> (handler));
}
private:
@@ -193,4 +198,7 @@ private:
boost::asio::streambuf m_buffer;
};
}
}
#endif

View File

@@ -1,199 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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.
*/
//==============================================================================
Socket::~Socket ()
{
}
#if ! BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
//-----------------------------------------------------------------------------
//
// Socket
//
void* Socket::this_layer_ptr (char const*) const
{
pure_virtual_called (__FILE__, __LINE__);
return nullptr;
}
//-----------------------------------------------------------------------------
//
// native_handle
//
bool Socket::native_handle (char const*, void*)
{
pure_virtual_called (__FILE__, __LINE__);
return false;
}
//-----------------------------------------------------------------------------
//
// basic_io_object
//
boost::asio::io_service& Socket::get_io_service ()
{
pure_virtual_called (__FILE__, __LINE__);
return *static_cast <boost::asio::io_service*>(nullptr);
}
//-----------------------------------------------------------------------------
//
// basic_socket
//
void* Socket::lowest_layer_ptr (char const*) const
{
pure_virtual_called (__FILE__, __LINE__);
return nullptr;
}
boost::system::error_code Socket::cancel (boost::system::error_code& ec)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
boost::system::error_code Socket::shutdown (shutdown_type, boost::system::error_code& ec)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
boost::system::error_code Socket::close (boost::system::error_code& ec)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//------------------------------------------------------------------------------
//
// basic_socket_acceptor
//
boost::system::error_code Socket::accept (Socket&, boost::system::error_code& ec)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
void Socket::async_accept (Socket&, SharedHandlerPtr handler)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error ());
}
//------------------------------------------------------------------------------
//
// basic_stream_socket
//
std::size_t Socket::read_some (MutableBuffers const&, boost::system::error_code& 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_called (__FILE__, __LINE__);
ec = pure_virtual_error ();
return 0;
}
void Socket::async_read_some (MutableBuffers const&, SharedHandlerPtr handler)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error (), 0);
}
void Socket::async_write_some (ConstBuffers const&, SharedHandlerPtr handler)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error (), 0);
}
//--------------------------------------------------------------------------
//
// ssl::stream
//
void* Socket::next_layer_ptr (char const*) const
{
pure_virtual_called (__FILE__, __LINE__);
return nullptr;
}
bool Socket::needs_handshake ()
{
return false;
}
void Socket::set_verify_mode (int)
{
pure_virtual_called (__FILE__, __LINE__);
}
boost::system::error_code Socket::handshake (handshake_type, boost::system::error_code& ec)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
void Socket::async_handshake (handshake_type, SharedHandlerPtr handler)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error ());
}
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
boost::system::error_code Socket::handshake (handshake_type,
ConstBuffers const&, boost::system::error_code& ec)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
void Socket::async_handshake (handshake_type, ConstBuffers const&, SharedHandlerPtr handler)
{
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_error (ec, __FILE__, __LINE__);
}
void Socket::async_shutdown (SharedHandlerPtr handler)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error ());
}
//------------------------------------------------------------------------------
#endif

View File

@@ -1,436 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_SOCKETS_SOCKET_H_INCLUDED
#define BEAST_ASIO_SOCKETS_SOCKET_H_INCLUDED
/** A high level socket abstraction.
This combines the capabilities of multiple socket interfaces such
as listening, connecting, streaming, and handshaking. It brings
everything together into a single abstract interface.
When member functions are called and the underlying implementation does
not support the operation, a fatal error is generated.
*/
class Socket
: public SocketBase
, public boost::asio::ssl::stream_base
, public boost::asio::socket_base
{
public:
virtual ~Socket ();
//--------------------------------------------------------------------------
//
// Socket
//
/** Retrieve the underlying object.
@note If the type doesn't match, nullptr is returned or an
exception is thrown if trying to acquire a reference.
*/
/** @{ */
template <typename Object>
Object& this_layer ()
{
Object* object (this->this_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <typename Object>
Object const& this_layer () const
{
Object const* object (this->this_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <typename Object>
Object* this_layer_ptr ()
{
return static_cast <Object*> (
this->this_layer_ptr (typeid (Object).name ()));
}
template <typename Object>
Object const* this_layer_ptr () const
{
return static_cast <Object const*> (
this->this_layer_ptr (typeid (Object).name ()));
}
/** @} */
virtual void* this_layer_ptr (char const* type_name) const
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
//
// native_handle
//
/** Retrieve the native representation of the object.
Since we dont know the return type, and because almost every
asio implementation passes the result by value, you need to provide
a pointer to a default-constructed object of the matching type.
@note If the type doesn't match, an exception is thrown.
*/
template <typename Handle>
void native_handle (Handle* dest)
{
if (! native_handle (typeid (Handle).name (), dest))
Throw (std::bad_cast (), __FILE__, __LINE__);
}
virtual bool native_handle (char const* type_name, void* dest)
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
//
// basic_io_object
//
virtual boost::asio::io_service& get_io_service ()
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
//
// basic_socket
//
/** Retrieve the lowest layer object.
@note If the type doesn't match, nullptr is returned or an
exception is thrown if trying to acquire a reference.
*/
/** @{ */
template <typename Object>
Object& lowest_layer ()
{
Object* object (this->lowest_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <typename Object>
Object const& lowest_layer () const
{
Object const* object (this->lowest_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <typename Object>
Object* lowest_layer_ptr ()
{
return static_cast <Object*> (
this->lowest_layer_ptr (typeid (Object).name ()));
}
template <typename Object>
Object const* lowest_layer_ptr () const
{
return static_cast <Object const*> (
this->lowest_layer_ptr (typeid (Object).name ()));
}
/** @} */
virtual void* lowest_layer_ptr (char const* type_name) const
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
void cancel ()
{
error_code ec;
throw_error (cancel (ec), __FILE__, __LINE__);
}
virtual error_code cancel (error_code& ec)
BEAST_SOCKET_VIRTUAL;
void shutdown (shutdown_type what)
{
error_code ec;
throw_error (shutdown (what, ec), __FILE__, __LINE__);
}
virtual error_code shutdown (shutdown_type what,
error_code& ec)
BEAST_SOCKET_VIRTUAL;
void close ()
{
error_code ec;
throw_error (close (ec), __FILE__, __LINE__);
}
virtual error_code close (error_code& ec)
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
//
// basic_socket_acceptor
//
virtual error_code accept (Socket& peer, error_code& ec)
BEAST_SOCKET_VIRTUAL;
template <typename AcceptHandler>
void async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
{
return async_accept (peer,
newAcceptHandler (BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)));
}
virtual void async_accept (Socket& peer, SharedHandlerPtr handler)
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
//
// basic_stream_socket
//
// SyncReadStream
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncReadStream.html
//
template <typename MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers,
error_code& ec)
{
return read_some (MutableBuffers (buffers), ec);
}
virtual std::size_t read_some (MutableBuffers const& buffers, error_code& ec)
BEAST_SOCKET_VIRTUAL;
// SyncWriteStream
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncWriteStream.html
//
template <typename ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, error_code &ec)
{
return write_some (ConstBuffers (buffers), ec);
}
virtual std::size_t write_some (ConstBuffers const& buffers, error_code& ec)
BEAST_SOCKET_VIRTUAL;
// AsyncReadStream
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncReadStream.html
//
template <typename MutableBufferSequence, typename ReadHandler>
void async_read_some (MutableBufferSequence const& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
return async_read_some (MutableBuffers (buffers),
newReadHandler (BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)));
}
virtual void async_read_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
BEAST_SOCKET_VIRTUAL;
// AsyncWriteStream
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncWriteStream.html
//
template <typename ConstBufferSequence, typename WriteHandler>
void async_write_some (ConstBufferSequence const& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
return async_write_some (ConstBuffers (buffers),
newWriteHandler (BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)));
}
virtual void async_write_some (ConstBuffers const& buffers, SharedHandlerPtr handler)
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
//
// ssl::stream
//
/** Retrieve the next layer object.
@note If the type doesn't match, nullptr is returned or an
exception is thrown if trying to acquire a reference.
*/
/** @{ */
template <typename Object>
Object& next_layer ()
{
Object* object (this->next_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <typename Object>
Object const& next_layer () const
{
Object const* object (this->next_layer_ptr <Object> ());
if (object == nullptr)
Throw (std::bad_cast (), __FILE__, __LINE__);
return *object;
}
template <typename Object>
Object* next_layer_ptr ()
{
return static_cast <Object*> (
this->next_layer_ptr (typeid (Object).name ()));
}
template <typename Object>
Object const* next_layer_ptr () const
{
return static_cast <Object const*> (
this->next_layer_ptr (typeid (Object).name ()));
}
/** @} */
virtual void* next_layer_ptr (char const* type_name) const
BEAST_SOCKET_VIRTUAL;
/** Determines if the underlying stream requires a handshake.
If needs_handshake is true, it will be necessary to call handshake or
async_handshake after the connection is established. Furthermore it
will be necessary to call the shutdown member from the
HandshakeInterface to close the connection. Do not close the underlying
socket or else the closure will not be graceful. Only one side should
initiate the handshaking shutdon. The other side should observe it.
Which side does what is up to the user.
The default version returns false.
*/
virtual bool needs_handshake ()
BEAST_SOCKET_VIRTUAL;
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__verify_mode.html
//
virtual void set_verify_mode (int verify_mode) = 0;
// ssl::stream::handshake (1 of 4)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload1.html
//
void handshake (handshake_type type)
{
error_code ec;
throw_error (handshake (type, ec), __FILE__, __LINE__);
}
// ssl::stream::handshake (2 of 4)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload2.html
//
virtual error_code handshake (handshake_type type, error_code& ec)
BEAST_SOCKET_VIRTUAL;
// ssl::stream::async_handshake (1 of 2)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload1.html
//
template <typename HandshakeHandler>
void async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
{
return async_handshake (type,
newHandshakeHandler (BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)));
}
virtual void async_handshake (handshake_type type, SharedHandlerPtr handler)
BEAST_SOCKET_VIRTUAL;
//--------------------------------------------------------------------------
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
// ssl::stream::handshake (3 of 4)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload3.html
//
template <typename ConstBufferSequence>
void handshake (handshake_type type, ConstBufferSequence const& buffers)
{
error_code ec;
throw_error (handshake (type, buffers, ec), __FILE__, __LINE__);
}
// ssl::stream::handshake (4 of 4)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload4.html
//
template <typename ConstBufferSequence>
error_code handshake (handshake_type type,
ConstBufferSequence const& buffers, error_code& ec)
{
return handshake (type, ConstBuffers (buffers), ec);
}
virtual error_code handshake (handshake_type type,
ConstBuffers const& buffers, error_code& ec)
BEAST_SOCKET_VIRTUAL;
// ssl::stream::async_handshake (2 of 2)
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload2.html
//
template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
void async_handshake (handshake_type type, ConstBufferSequence const& buffers,
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
{
return async_handshake (type, ConstBuffers (buffers),
newBufferedHandshakeHandler (BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)));
}
virtual void async_handshake (handshake_type type, ConstBuffers const& buffers,
SharedHandlerPtr handler)
BEAST_SOCKET_VIRTUAL;
#endif
//--------------------------------------------------------------------------
// ssl::stream::shutdown
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/shutdown.html
//
void shutdown ()
{
error_code ec;
throw_error (shutdown (ec), __FILE__, __LINE__);
}
virtual error_code shutdown (error_code& ec)
BEAST_SOCKET_VIRTUAL;
// ssl::stream::async_shutdown
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_shutdown.html
//
template <typename ShutdownHandler>
void async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
{
return async_shutdown (
newShutdownHandler (BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler)));
}
virtual void async_shutdown (SharedHandlerPtr handler)
BEAST_SOCKET_VIRTUAL;
};
#endif

View File

@@ -1,42 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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.
*/
//==============================================================================
boost::system::error_code SocketBase::pure_virtual_error ()
{
return boost::system::errc::make_error_code (
boost::system::errc::function_not_supported);
}
boost::system::error_code SocketBase::pure_virtual_error (error_code& ec,
char const* fileName, int lineNumber)
{
pure_virtual_called (fileName, lineNumber);
return ec = pure_virtual_error ();
}
void SocketBase::pure_virtual_called (char const* fileName, int lineNumber)
{
Throw (std::runtime_error ("pure virtual called"), fileName, lineNumber);
}
void SocketBase::throw_error (error_code const& ec, char const* fileName, int lineNumber)
{
if (ec)
Throw (boost::system::system_error (ec), fileName, lineNumber);
}

View File

@@ -1,49 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_SOCKETS_SOCKETBASE_H_INCLUDED
#define BEAST_ASIO_SOCKETS_SOCKETBASE_H_INCLUDED
/** Common implementation details for Socket and related classes.
Normally you wont need to use this.
*/
struct SocketBase
{
public:
typedef boost::system::error_code error_code;
/** The error returned when a pure virtual is called.
This is mostly academic since a pure virtual call generates
a fatal error but in case that gets disabled, this will at
least return a suitable error code.
*/
static error_code pure_virtual_error ();
/** Convenience for taking a reference and returning the error_code. */
static error_code pure_virtual_error (error_code& ec,
char const* fileName, int lineNumber);
/** Called when a function doesn't support the interface. */
static void pure_virtual_called (char const* fileName, int lineNumber);
/** Called when synchronous functions without error parameters get an error. */
static void throw_error (error_code const& ec, char const* fileName, int lineNumber);
};
#endif

View File

@@ -1,838 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_SOCKETS_SOCKETWRAPPER_H_INCLUDED
#define BEAST_ASIO_SOCKETS_SOCKETWRAPPER_H_INCLUDED
/** Wraps a reference to any object and exports all availble interfaces.
If the object does not support an interface, calling those
member functions will behave as if a pure virtual was called.
Note that only a reference to the underlying is stored. Management
of the lifetime of the object is controlled by the caller.
Examples of the type of Object:
asio::ip::tcp::socket
asio::ip::tcp::socket&
asio::ssl::stream <asio::ip::tcp::socket>
asio::ssl::stream <asio::ip::tcp::socket&>
explain arg must be an io_context
explain SocketWrapper will create and take ownership of the tcp::socket
explain this_layer_type will be tcp::socket
explain next_layer () returns a asio::ip::tcp::socket&
explain lowest_layer () returns a asio::ip::tcp::socket&
asio::ssl::stream <asio::buffered_stream <asio::ip::tcp::socket> > >
This makes my head explode
*/
//------------------------------------------------------------------------------
namespace detail
{
namespace SocketWrapperMemberChecks
{
BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_lowest_layer, lowest_layer);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_cancel, cancel);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_shutdown, shutdown);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_close, close);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_accept, accept);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_accept, async_accept);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_read_some, read_some);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_write_some, write_some);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_read_some, async_read_some);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_write_some, async_write_some);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_set_verify_mode, set_verify_mode);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_handshake, handshake);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_handshake, async_handshake);
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_shutdown, async_shutdown);
// Extracts the underlying socket type from the protocol of another asio object
template <typename T, typename Enable = void>
struct native_socket
{
typedef void* socket_type;
inline native_socket (Socket&)
: m_socket (nullptr)
{
SocketBase::pure_virtual_called (__FILE__, __LINE__);
}
inline socket_type& get ()
{
SocketBase::pure_virtual_called (__FILE__, __LINE__);
return m_socket;
}
inline socket_type& operator-> ()
{
return get ();
}
private:
socket_type m_socket;
};
// Enabled if T::protocol_type::socket exists as a type
template <typename T>
struct native_socket <T, typename boost::enable_if <boost::is_class <
typename T::protocol_type::socket> >::type>
{
typedef typename T::protocol_type::socket socket_type;
inline native_socket (Socket& peer)
: m_socket_ptr (&peer.this_layer <socket_type> ())
{
}
inline socket_type& get () noexcept
{
return *m_socket_ptr;
}
inline socket_type& operator-> () noexcept
{
return get ();
}
private:
socket_type* m_socket_ptr;
};
}
}
//------------------------------------------------------------------------------
template <typename Object>
class SocketWrapper
: public Socket
, public Uncopyable
{
public:
// Converts a static bool constexpr member named 'value' into
// an IntegralConstant for SFINAE overload resolution.
//
template <class Cond>
struct Enabled : public IntegralConstant <bool, Cond::value> { };
template <typename Arg>
explicit SocketWrapper (Arg& arg)
: m_object (arg)
{
}
template <typename Arg1, typename Arg2>
SocketWrapper (Arg1& arg1, Arg2& arg2)
: m_object (arg1, arg2)
{
}
//--------------------------------------------------------------------------
//
// SocketWrapper
//
/** The type of the object being wrapped. */
typedef typename boost::remove_reference <Object>::type this_layer_type;
/** Get a reference to this layer. */
this_layer_type& this_layer () noexcept
{
return m_object;
}
/** Get a const reference to this layer. */
this_layer_type const& this_layer () const noexcept
{
return m_object;
}
//--------------------------------------------------------------------------
//
// Socket
//
void* this_layer_ptr (char const* type_name) const
{
char const* const name (typeid (this_layer_type).name ());
if (strcmp (name, type_name) == 0)
return const_cast <void*> (static_cast <void const*> (&m_object));
return nullptr;
}
//--------------------------------------------------------------------------
//
// native_handle
//
#if 0
// This is a potential work-around for the problem with
// the has_type_native_handle_type template, but requires
// Boost 1.54 or later.
//
// This include will be needed:
//
// boost/tti/has_type.hpp
//
//
BOOST_TTI_HAS_TYPE(native_handle_type)
#else
template <class T>
struct has_type_native_handle_type
{
typedef char yes;
typedef struct {char dummy[2];} no;
template <class C> static yes f(typename C::native_handle_type*);
template <class C> static no f(...);
#ifdef _MSC_VER
static bool const value = sizeof(f<T>(0)) == 1;
#else
// This line fails to compile under Visual Studio 2012
static bool const value = sizeof(has_type_native_handle_type<T>::f<T>(0)) == 1;
#endif
};
#endif
template <typename T, bool Exists = has_type_native_handle_type <T>::value >
struct extract_native_handle_type
{
typedef typename T::native_handle_type type;
};
template <typename T>
struct extract_native_handle_type <T, false>
{
typedef void type;
};
// This will be void if native_handle_type doesn't exist in Object
typedef typename extract_native_handle_type <this_layer_type>::type native_handle_type;
bool native_handle (char const* type_name, void* dest)
{
using namespace detail::SocketWrapperMemberChecks;
return native_handle (type_name, dest,
Enabled <has_type_native_handle_type <this_layer_type> > ());
}
bool native_handle (char const* type_name, void* dest,
TrueType)
{
char const* const name (typeid (typename this_layer_type::native_handle_type).name ());
if (strcmp (name, type_name) == 0)
{
native_handle_type* const p (reinterpret_cast <native_handle_type*> (dest));
*p = m_object.native_handle ();
return true;
}
return false;
}
bool native_handle (char const*, void*,
FalseType)
{
pure_virtual_called (__FILE__, __LINE__);
return false;
}
//--------------------------------------------------------------------------
//
// basic_io_object
//
boost::asio::io_service& get_io_service ()
{
#if 0
// Apparently has_get_io_service always results in false
using namespace detail::SocketWrapperMemberChecks;
return get_io_service (
Enabled <has_get_io_service <this_layer_type,
boost::asio::io_service&()> > ());
#else
return get_io_service (TrueType ());
#endif
}
boost::asio::io_service& get_io_service (
TrueType)
{
return m_object.get_io_service ();
}
boost::asio::io_service& get_io_service (
FalseType)
{
pure_virtual_called (__FILE__, __LINE__);
return *static_cast <boost::asio::io_service*>(nullptr);
}
//--------------------------------------------------------------------------
//
// basic_socket
//
/*
To forward the lowest_layer_type type, we need to make sure it
exists in Object. This is a little more tricky than just figuring
out if Object has a particular member function.
The problem is boost::asio::basic_socket_acceptor, which doesn't
have lowest_layer () or lowest_layer_type ().
*/
template <class T>
struct has_type_lowest_layer_type
{
typedef char yes;
typedef struct {char dummy[2];} no;
template <class C> static yes f(typename C::lowest_layer_type*);
template <class C> static no f(...);
#ifdef _MSC_VER
static bool const value = sizeof(f<T>(0)) == 1;
#else
// This line fails to compile under Visual Studio 2012
static bool const value = sizeof(has_type_lowest_layer_type<T>::f<T>(0)) == 1;
#endif
};
template <typename T, bool Exists = has_type_lowest_layer_type <T>::value >
struct extract_lowest_layer_type
{
typedef typename T::lowest_layer_type type;
};
template <typename T>
struct extract_lowest_layer_type <T, false>
{
typedef void type;
};
// This will be void if lowest_layer_type doesn't exist in Object
typedef typename extract_lowest_layer_type <this_layer_type>::type lowest_layer_type;
void* lowest_layer_ptr (char const* type_name) const
{
using namespace detail::SocketWrapperMemberChecks;
return lowest_layer_ptr (type_name,
Enabled <has_type_lowest_layer_type <this_layer_type> > ());
}
void* lowest_layer_ptr (char const* type_name,
TrueType) const
{
char const* const name (typeid (typename this_layer_type::lowest_layer_type).name ());
if (strcmp (name, type_name) == 0)
return const_cast <void*> (static_cast <void const*> (&m_object.lowest_layer ()));
return nullptr;
}
void* lowest_layer_ptr (char const*,
FalseType) const
{
pure_virtual_called (__FILE__, __LINE__);
return nullptr;
}
//--------------------------------------------------------------------------
error_code cancel (error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return cancel (ec,
Enabled <has_cancel <this_layer_type,
error_code (error_code&)> > ());
}
error_code cancel (error_code& ec,
TrueType)
{
return m_object.cancel (ec);
}
error_code cancel (error_code& ec,
FalseType)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
error_code shutdown (shutdown_type what, error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return shutdown (what, ec,
Enabled <has_shutdown <this_layer_type,
error_code (shutdown_type, error_code&)> > ());
}
error_code shutdown (shutdown_type what, error_code& ec,
TrueType)
{
return m_object.shutdown (what, ec);
}
error_code shutdown (shutdown_type, error_code& ec,
FalseType)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
error_code close (error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return close (ec,
Enabled <has_close <this_layer_type,
error_code (error_code&)> > ());
}
error_code close (error_code& ec,
TrueType)
{
return m_object.close (ec);
}
error_code close (error_code& ec,
FalseType)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
//
// basic_socket_acceptor
//
error_code accept (Socket& peer, error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
typedef typename native_socket <this_layer_type>::socket_type socket_type;
return accept (peer, ec,
Enabled <has_accept <this_layer_type,
error_code (socket_type&, error_code&)> > ());
}
error_code accept (Socket& peer, error_code& ec,
TrueType)
{
using namespace detail::SocketWrapperMemberChecks;
return m_object.accept (
native_socket <this_layer_type> (peer).get (), ec);
}
error_code accept (Socket&, error_code& ec,
FalseType)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
void async_accept (Socket& peer, SharedHandlerPtr handler)
{
using namespace detail::SocketWrapperMemberChecks;
typedef typename native_socket <this_layer_type>::socket_type socket_type;
async_accept (peer, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
Enabled <has_async_accept <this_layer_type,
void (socket_type&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))> > ());
}
void async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
TrueType)
{
using namespace detail::SocketWrapperMemberChecks;
m_object.async_accept (
native_socket <this_layer_type> (peer).get (),
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
}
void async_accept (Socket&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
FalseType)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error ());
}
//--------------------------------------------------------------------------
//
// basic_stream_socket
//
std::size_t read_some (MutableBuffers const& buffers, error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return read_some (buffers, ec,
Enabled <has_read_some <this_layer_type,
std::size_t (MutableBuffers const&, error_code&)> > ());
}
template <typename MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec,
TrueType)
{
return m_object.read_some (buffers, ec);
}
template <typename MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const&, error_code& ec,
FalseType)
{
pure_virtual_called (__FILE__, __LINE__);
ec = pure_virtual_error ();
return 0;
}
//--------------------------------------------------------------------------
std::size_t write_some (ConstBuffers const& buffers, error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return write_some (buffers, ec,
Enabled <has_write_some <this_layer_type,
std::size_t (ConstBuffers const&, error_code&)> > ());
}
template <typename ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec,
TrueType)
{
return m_object.write_some (buffers, ec);
}
template <typename ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const&, error_code& ec,
FalseType)
{
pure_virtual_called (__FILE__, __LINE__);
ec = pure_virtual_error ();
return 0;
}
//--------------------------------------------------------------------------
void async_read_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
{
using namespace detail::SocketWrapperMemberChecks;
async_read_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
Enabled <has_async_read_some <this_layer_type,
void (MutableBuffers const&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))> > ());
}
void async_read_some (MutableBuffers const& buffers,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
TrueType)
{
m_object.async_read_some (buffers,
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
}
void async_read_some (MutableBuffers const&,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
FalseType)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error (), 0);
}
//--------------------------------------------------------------------------
void async_write_some (ConstBuffers const& buffers, SharedHandlerPtr handler)
{
using namespace detail::SocketWrapperMemberChecks;
async_write_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
Enabled <has_async_write_some <this_layer_type,
void (ConstBuffers const&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))> > ());
}
void async_write_some (ConstBuffers const& buffers,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
TrueType)
{
m_object.async_write_some (buffers,
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
}
void async_write_some (ConstBuffers const&,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
FalseType)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error (), 0);
}
//--------------------------------------------------------------------------
//
// ssl::stream
//
template <class T>
struct has_type_next_layer_type
{
typedef char yes;
typedef struct {char dummy[2];} no;
template <class C> static yes f(typename C::next_layer_type*);
template <class C> static no f(...);
#ifdef _MSC_VER
static bool const value = sizeof(f<T>(0)) == 1;
#else
// This line fails to compile under Visual Studio 2012
static bool const value = sizeof(has_type_next_layer_type<T>::f<T>(0)) == 1;
#endif
};
template <typename T, bool Exists = has_type_next_layer_type <T>::value >
struct extract_next_layer_type
{
typedef typename T::next_layer_type type;
};
template <typename T>
struct extract_next_layer_type <T, false>
{
typedef void type;
};
// This will be void if next_layer_type doesn't exist in Object
typedef typename extract_next_layer_type <this_layer_type>::type next_layer_type;
void* next_layer_ptr (char const* type_name) const
{
using namespace detail::SocketWrapperMemberChecks;
return next_layer_ptr (type_name,
Enabled <has_type_next_layer_type <this_layer_type> > ());
}
void* next_layer_ptr (char const* type_name,
TrueType) const
{
char const* const name (typeid (typename this_layer_type::next_layer_type).name ());
if (strcmp (name, type_name) == 0)
return const_cast <void*> (static_cast <void const*> (&m_object.next_layer ()));
return nullptr;
}
void* next_layer_ptr (char const*,
FalseType) const
{
pure_virtual_called (__FILE__, __LINE__);
return nullptr;
}
//--------------------------------------------------------------------------
bool needs_handshake ()
{
using namespace detail::SocketWrapperMemberChecks;
return
has_handshake <this_layer_type,
error_code (handshake_type, error_code&)>::value ||
has_async_handshake <this_layer_type,
void (handshake_type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value;
}
//--------------------------------------------------------------------------
void set_verify_mode (int verify_mode)
{
using namespace detail::SocketWrapperMemberChecks;
set_verify_mode (verify_mode,
Enabled <has_set_verify_mode <this_layer_type,
void (int)> > ());
}
void set_verify_mode (int verify_mode,
TrueType)
{
m_object.set_verify_mode (verify_mode);
}
void set_verify_mode (int,
FalseType)
{
pure_virtual_called (__FILE__, __LINE__);
}
//--------------------------------------------------------------------------
error_code handshake (handshake_type type, error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return handshake (type, ec,
Enabled <has_handshake <this_layer_type,
error_code (handshake_type, error_code&)> > ());
}
error_code handshake (handshake_type type, error_code& ec,
TrueType)
{
return m_object.handshake (type, ec);
}
error_code handshake (handshake_type, error_code& ec,
FalseType)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
void async_handshake (handshake_type type, SharedHandlerPtr handler)
{
using namespace detail::SocketWrapperMemberChecks;
async_handshake (type, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
Enabled <has_async_handshake <this_layer_type,
void (handshake_type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))> > ());
}
void async_handshake (handshake_type type,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
TrueType)
{
m_object.async_handshake (type,
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
}
void async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
FalseType)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error ());
}
//--------------------------------------------------------------------------
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
error_code handshake (handshake_type type,
ConstBuffers const& buffers, error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return handshake (type, buffers, ec,
Enabled <has_handshake <this_layer_type,
error_code (handshake_type, ConstBuffers const&, error_code&)> > ());
}
error_code handshake (handshake_type type,
ConstBuffers const& buffers, error_code& ec,
TrueType)
{
return m_object.handshake (type, buffers, ec);
}
error_code handshake (handshake_type, ConstBuffers const&, error_code& ec,
FalseType)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
void async_handshake (handshake_type type,
ConstBuffers const& buffers, SharedHandlerPtr handler)
{
using namespace detail::SocketWrapperMemberChecks;
async_handshake (type, buffers,
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
Enabled <has_async_handshake <this_layer_type,
void (handshake_type, ConstBuffers const&,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))> > ());
}
void async_handshake (handshake_type type, ConstBuffers const& buffers,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
TrueType)
{
m_object.async_handshake (type, buffers,
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
}
void async_handshake (handshake_type, ConstBuffers const&,
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
FalseType)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error (), 0);
}
#endif
//--------------------------------------------------------------------------
error_code shutdown (error_code& ec)
{
using namespace detail::SocketWrapperMemberChecks;
return shutdown (ec,
Enabled <has_shutdown <this_layer_type,
error_code (error_code&)> > ());
}
error_code shutdown (error_code& ec,
TrueType)
{
return m_object.shutdown (ec);
}
error_code shutdown (error_code& ec,
FalseType)
{
return pure_virtual_error (ec, __FILE__, __LINE__);
}
//--------------------------------------------------------------------------
void async_shutdown (SharedHandlerPtr handler)
{
using namespace detail::SocketWrapperMemberChecks;
async_shutdown (BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
Enabled <has_async_shutdown <this_layer_type,
void (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))> > ());
}
void async_shutdown (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
TrueType)
{
m_object.async_shutdown (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
}
void async_shutdown (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
FalseType)
{
get_io_service ().wrap (
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
(pure_virtual_error ());
}
private:
Object m_object;
};
#endif

View File

@@ -1,66 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_ASIO_SOCKETS_SOCKETWRAPPERSTRAND_H_INCLUDED
#define BEAST_ASIO_SOCKETS_SOCKETWRAPPERSTRAND_H_INCLUDED
/** Wraps the async I/O of a SocketWrapper with an io_service::strand
To use this in a chain of wrappers, customize the Base type.
*/
template <typename Object, typename Base = SocketWrapper <Object> >
class SocketWrapperStrand
: public Base
{
public:
template <typename Arg>
SocketWrapperStrand (Arg& arg)
: Base (arg)
, m_strand (this->get_io_service ())
{
}
template <typename Arg1, typename Arg2>
SocketWrapperStrand (Arg1& arg1, Arg2& arg2)
: Base (arg1, arg2)
, m_strand (this->get_io_service ())
{
}
//--------------------------------------------------------------------------
//
// basic_stream_socket
//
void async_read_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
{
this->Base::async_read_some (buffers,
newReadHandler (m_strand.wrap (handler)));
}
void async_write_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
{
this->Base::async_write_some (buffers,
newWriteHandler (m_strand.wrap (handler)));
}
protected:
boost::asio::io_service::strand m_strand;
};
#endif

View File

@@ -53,6 +53,9 @@
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
// work-around for broken <boost/get_pointer.hpp>
#include "../../../beast/boost/get_pointer.h"
// Continuation hooks added in 1.54.0
#ifndef BEAST_ASIO_HAS_CONTINUATION_HOOKS
# if BOOST_VERSION >= 105400

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace beast {
/** Test for showing information about the build of boost.
*/
class BoostUnitTests : public UnitTest
@@ -80,3 +82,5 @@ public:
};
static BoostUnitTests boostUnitTests;
}

View File

@@ -17,6 +17,9 @@
*/
//==============================================================================
namespace beast {
namespace asio {
PeerTest::Result::Result ()
: m_ec (TestPeerBasics::make_error (TestPeerBasics::errc::skipped))
, m_message (m_ec.message ())
@@ -98,3 +101,6 @@ bool PeerTest::Results::report (UnitTest& test, bool beginTestCase) const
success = false;
return success;
}
}
}

View File

@@ -20,8 +20,10 @@
#ifndef BEAST_ASIO_TESTS_PEERTEST_H_INCLUDED
#define BEAST_ASIO_TESTS_PEERTEST_H_INCLUDED
/** Performs a test of two peers defined by template parameters.
*/
namespace beast {
namespace asio {
/** Performs a test of two peers defined by template parameters. */
class PeerTest
{
public:
@@ -236,4 +238,7 @@ public:
}
};
}
}
#endif

View File

@@ -20,8 +20,10 @@
#ifndef BEAST_ASIO_TESTS_TESTPEER_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEER_H_INCLUDED
/** An abstract peer for unit tests.
*/
namespace beast {
namespace asio {
/** An abstract peer for unit tests. */
class TestPeer : public TestPeerBasics
{
public:
@@ -50,4 +52,7 @@ public:
virtual boost::system::error_code join () = 0;
};
}
}
#endif

View File

@@ -17,6 +17,9 @@
*/
//==============================================================================
namespace beast {
namespace asio {
TestPeerBasics::Model::Model (model_t model)
: m_model (model)
{
@@ -153,3 +156,6 @@ void TestPeerBasics::breakpoint (boost::system::error_code const& ec)
void TestPeerBasics::breakpoint (char const* const)
{
}
}
}

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERBASICS_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERBASICS_H_INCLUDED
namespace beast {
namespace asio {
/** Common declarations for TestPeer.
@see TestPeer
@@ -103,4 +106,7 @@ public:
static void breakpoint (char const* const message);
};
}
}
#endif

View File

@@ -20,8 +20,12 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERDETAILS_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERDETAILS_H_INCLUDED
/** Base class of all detail objects.
*/
#include "../../../beast/asio/abstract_socket.h"
namespace beast {
namespace asio {
/** Base class of all detail objects. */
class TestPeerDetails
{
public:
@@ -29,9 +33,9 @@ public:
virtual String name () const = 0;
virtual Socket& get_socket () = 0;
virtual abstract_socket& get_socket () = 0;
virtual Socket& get_acceptor () = 0;
virtual abstract_socket& get_acceptor () = 0;
boost::asio::io_service& get_io_service ()
{
@@ -42,4 +46,7 @@ private:
boost::asio::io_service m_io_service;
};
}
}
#endif

View File

@@ -20,8 +20,12 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERDETAILSTCP_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERDETAILSTCP_H_INCLUDED
/** Some predefined Detail classes for TestPeer
*/
#include "../../../beast/asio/socket_wrapper.h"
namespace beast {
namespace asio {
/** Some predefined Detail classes for TestPeer */
struct TcpDetails : public TestPeerDetails
{
protected:
@@ -59,12 +63,12 @@ public:
return getArgName (m_protocol);
}
Socket& get_socket ()
abstract_socket& get_socket ()
{
return m_socket_wrapper;
}
Socket& get_acceptor ()
abstract_socket& get_acceptor ()
{
return m_acceptor_wrapper;
}
@@ -101,8 +105,11 @@ protected:
protocol_type m_protocol;
socket_type m_socket;
acceptor_type m_acceptor;
SocketWrapper <socket_type&> m_socket_wrapper;
SocketWrapper <acceptor_type&> m_acceptor_wrapper;
socket_wrapper <socket_type&> m_socket_wrapper;
socket_wrapper <acceptor_type&> m_acceptor_wrapper;
};
}
}
#endif

View File

@@ -17,7 +17,10 @@
*/
//==============================================================================
TestPeerLogic::TestPeerLogic (Socket& socket)
namespace beast {
namespace asio {
TestPeerLogic::TestPeerLogic (abstract_socket& socket)
: m_socket (&socket)
{
}
@@ -37,7 +40,7 @@ TestPeerLogic::error_code const& TestPeerLogic::error (error_code const& ec) noe
return m_ec = ec;
}
Socket& TestPeerLogic::socket () noexcept
abstract_socket& TestPeerLogic::socket () noexcept
{
return *m_socket;
}
@@ -61,3 +64,6 @@ void TestPeerLogic::pure_virtual ()
{
fatal_error ("A TestPeerLogic function was called incorrectly");
}
}
}

View File

@@ -20,20 +20,22 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGIC_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGIC_H_INCLUDED
/** Interface for implementing the logic part of a peer test.
*/
namespace beast {
namespace asio {
/** Interface for implementing the logic part of a peer test. */
class TestPeerLogic : public TestPeerBasics
{
public:
typedef boost::system::error_code error_code;
explicit TestPeerLogic (Socket& socket);
explicit TestPeerLogic (abstract_socket& socket);
error_code& error () noexcept;
error_code const& error () const noexcept;
error_code const& error (error_code const& ec) noexcept; // assigns to m_ec
Socket& socket () noexcept;
abstract_socket& socket () noexcept;
virtual PeerRole get_role () const noexcept = 0;
@@ -51,7 +53,10 @@ public:
private:
error_code m_ec;
Socket* m_socket;
abstract_socket* m_socket;
};
}
}
#endif

View File

@@ -17,7 +17,10 @@
*/
//==============================================================================
TestPeerLogicAsyncClient::TestPeerLogicAsyncClient (Socket& socket)
namespace beast {
namespace asio {
TestPeerLogicAsyncClient::TestPeerLogicAsyncClient (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
@@ -39,7 +42,7 @@ void TestPeerLogicAsyncClient::on_connect_async (error_code const& ec)
if (socket ().needs_handshake ())
{
socket ().async_handshake (Socket::client,
socket ().async_handshake (abstract_socket::client,
boost::bind (&TestPeerLogicAsyncClient::on_handshake, this,
boost::asio::placeholders::error));
}
@@ -108,7 +111,7 @@ void TestPeerLogicAsyncClient::on_read_final (error_code const& ec, std::size_t)
{
// on_shutdown will call finished ()
error_code ec;
on_shutdown (socket ().shutdown (Socket::shutdown_send, ec));
on_shutdown (socket ().shutdown (abstract_socket::shutdown_send, ec));
}
}
else
@@ -137,7 +140,7 @@ void TestPeerLogicAsyncClient::on_shutdown (error_code const& ec)
{
if (socket ().needs_handshake ())
{
socket ().shutdown (Socket::shutdown_send, error ());
socket ().shutdown (abstract_socket::shutdown_send, error ());
}
if (! error ())
@@ -153,3 +156,6 @@ void TestPeerLogicAsyncClient::on_shutdown (error_code const& ec)
finished ();
}
}
}

View File

@@ -20,10 +20,13 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicAsyncClient : public TestPeerLogic
{
public:
explicit TestPeerLogicAsyncClient (Socket& socket);
explicit TestPeerLogicAsyncClient (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect_async (error_code const& ec);
@@ -36,4 +39,7 @@ private:
boost::asio::streambuf m_buf;
};
}
}
#endif

View File

@@ -17,7 +17,10 @@
*/
//==============================================================================
TestPeerLogicAsyncServer::TestPeerLogicAsyncServer (Socket& socket)
namespace beast {
namespace asio {
TestPeerLogicAsyncServer::TestPeerLogicAsyncServer (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
@@ -39,7 +42,7 @@ void TestPeerLogicAsyncServer::on_connect_async (error_code const& ec)
if (socket ().needs_handshake ())
{
socket ().async_handshake (Socket::server,
socket ().async_handshake (abstract_socket::server,
boost::bind (&TestPeerLogicAsyncServer::on_handshake, this,
boost::asio::placeholders::error));
}
@@ -90,7 +93,7 @@ void TestPeerLogicAsyncServer::on_write (error_code const& ec, std::size_t bytes
// on_shutdown will call finished ()
// we need another instance of ec so we can call on_shutdown()
error_code ec;
on_shutdown (socket ().shutdown (Socket::shutdown_receive, ec));
on_shutdown (socket ().shutdown (abstract_socket::shutdown_receive, ec));
}
}
@@ -102,7 +105,7 @@ void TestPeerLogicAsyncServer::on_shutdown (error_code const& ec)
{
if (socket ().needs_handshake ())
{
socket ().shutdown (Socket::shutdown_receive, error ());
socket ().shutdown (abstract_socket::shutdown_receive, error ());
}
if (success (socket ().close (error ())))
@@ -115,3 +118,7 @@ void TestPeerLogicAsyncServer::on_shutdown (error_code const& ec)
finished ();
}
}
}

View File

@@ -20,10 +20,13 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICASYNCSERVER_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICASYNCSERVER_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicAsyncServer : public TestPeerLogic
{
public:
explicit TestPeerLogicAsyncServer (Socket& socket);
explicit TestPeerLogicAsyncServer (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect_async (error_code const& ec);
@@ -35,4 +38,7 @@ private:
boost::asio::streambuf m_buf;
};
}
}
#endif

View File

@@ -17,7 +17,10 @@
*/
//==============================================================================
TestPeerLogicProxyClient::TestPeerLogicProxyClient (Socket& socket)
namespace beast {
namespace asio {
TestPeerLogicProxyClient::TestPeerLogicProxyClient (abstract_socket& socket)
: TestPeerLogicSyncClient (socket)
{
}
@@ -33,3 +36,7 @@ void TestPeerLogicProxyClient::on_pre_handshake ()
boost::asio::write (socket (), boost::asio::buffer (line), error ());
}
}
}

View File

@@ -20,12 +20,18 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
namespace beast {
namespace asio {
/** A synchronous client logic that sends a PROXY protocol pre-handshake. */
class TestPeerLogicProxyClient : public TestPeerLogicSyncClient
{
public:
explicit TestPeerLogicProxyClient (Socket& socket);
explicit TestPeerLogicProxyClient (abstract_socket& socket);
void on_pre_handshake ();
};
}
}
#endif

View File

@@ -17,7 +17,10 @@
*/
//==============================================================================
TestPeerLogicSyncClient::TestPeerLogicSyncClient (Socket& socket)
namespace beast {
namespace asio {
TestPeerLogicSyncClient::TestPeerLogicSyncClient (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
@@ -97,7 +100,7 @@ void TestPeerLogicSyncClient::on_connect ()
error () = error_code ();
}
if (failure (socket ().shutdown (Socket::shutdown_send, error ())))
if (failure (socket ().shutdown (abstract_socket::shutdown_send, error ())))
return;
if (failure (socket ().close (error ())))
@@ -107,3 +110,6 @@ void TestPeerLogicSyncClient::on_connect ()
void TestPeerLogicSyncClient::on_pre_handshake ()
{
}
}
}

View File

@@ -20,14 +20,20 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicSyncClient : public TestPeerLogic
{
public:
explicit TestPeerLogicSyncClient (Socket& socket);
explicit TestPeerLogicSyncClient (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect ();
virtual void on_pre_handshake ();
};
}
}
#endif

View File

@@ -17,7 +17,10 @@
*/
//==============================================================================
TestPeerLogicSyncServer::TestPeerLogicSyncServer (Socket& socket)
namespace beast {
namespace asio {
TestPeerLogicSyncServer::TestPeerLogicSyncServer (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
@@ -72,9 +75,12 @@ void TestPeerLogicSyncServer::on_connect ()
return;
}
if (failure (socket ().shutdown (Socket::shutdown_send, error ())))
if (failure (socket ().shutdown (abstract_socket::shutdown_send, error ())))
return;
if (failure (socket ().close (error ())))
return;
}
}
}

View File

@@ -20,13 +20,19 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICSYNCSERVER_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICSYNCSERVER_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicSyncServer : public TestPeerLogic
{
public:
explicit TestPeerLogicSyncServer (Socket& socket);
explicit TestPeerLogicSyncServer (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect ();
};
}
}
#endif

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_TESTS_TESTPEERTYPE_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERTYPE_H_INCLUDED
namespace beast {
namespace asio {
template <typename Logic, typename Details>
class TestPeerType
: public Details
@@ -392,4 +395,7 @@ private:
int m_timeoutSeconds;
};
}
}
#endif

View File

@@ -17,8 +17,10 @@
*/
//==============================================================================
/** UnitTest for the TestPeer family of objects.
*/
namespace beast {
namespace asio {
/** UnitTest for the TestPeer family of objects. */
class TestPeerUnitTests : public UnitTest
{
public:
@@ -49,3 +51,6 @@ public:
};
static TestPeerUnitTests testPeerUnitTests;
}
}

View File

@@ -148,7 +148,6 @@ class FileOutputStream;
#include "maths/Math.h"
#include "logging/Logger.h"
#include "diagnostic/FPUFlags.h"
#include "memory/SharedFunction.h"
#include "text/Identifier.h"
#include "containers/Variant.h"
#include "containers/LinkedListPointer.h"

View File

@@ -1,334 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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_CORE_SHAREDFUNCTION_H_INCLUDED
#define BEAST_CORE_SHAREDFUNCTION_H_INCLUDED
/** A reference counted, abstract function object. */
template <typename Signature, class Allocator = std::allocator <char> >
class SharedFunction;
//------------------------------------------------------------------------------
template <class R, class A>
class SharedFunction <R (void), A>
{
public:
struct Call : SharedObject
{ virtual R operator() () = 0; };
template <typename F>
struct CallType : Call
{
typedef typename A:: template rebind <CallType <F> >::other Allocator;
CallType (BEAST_MOVE_ARG(F) f, A a = A ())
: m_f (BEAST_MOVE_CAST(F)(f)), m_a (a)
{ }
R operator() ()
{ return (m_f)(); }
private:
F m_f;
Allocator m_a;
};
typedef R result_type;
template <typename F>
explicit SharedFunction (F f, A a = A ())
: m_ptr (new (typename CallType <F>::Allocator (a).allocate (1))
CallType <F> (BEAST_MOVE_CAST(F)(f), a))
{ }
SharedFunction (SharedFunction const& other, A)
: m_ptr (other.m_ptr)
{ }
SharedFunction ()
{ }
bool empty () const
{ return m_ptr == nullptr; }
R operator() () const
{ return (*m_ptr)(); }
private:
SharedPtr <Call> m_ptr;
};
//------------------------------------------------------------------------------
template <class R, class P1, class A>
class SharedFunction <R (P1), A>
{
public:
struct Call : public SharedObject
{ virtual R operator() (P1 const& p1) = 0; };
template <typename F>
struct CallType : Call
{
typedef typename A:: template rebind <CallType <F> >::other Allocator;
CallType (BEAST_MOVE_ARG(F) f, A a = A ())
: m_f (BEAST_MOVE_CAST(F)(f)), m_a (a)
{ }
R operator() (P1 const& p1)
{ return (m_f)(p1); }
private:
F m_f;
Allocator m_a;
};
typedef R result_type;
template <typename F>
SharedFunction (F f, A a = A ())
: m_ptr (new (typename CallType <F>::Allocator (a).allocate (1))
CallType <F> (BEAST_MOVE_CAST(F)(f), a))
{ }
SharedFunction (SharedFunction const& other, A)
: m_ptr (other.m_ptr)
{ }
SharedFunction ()
{ }
bool empty () const
{ return m_ptr == nullptr; }
R operator() (P1 const& p1) const
{ return (*m_ptr)(p1); }
private:
SharedPtr <Call> m_ptr;
};
//------------------------------------------------------------------------------
template <class R, class P1, class P2, class A>
class SharedFunction <R (P1, P2), A>
{
public:
struct Call : public SharedObject
{ virtual R operator() (P1 const& p1, P2 const& p2) = 0; };
template <typename F>
struct CallType : Call
{
typedef typename A:: template rebind <CallType <F> >::other Allocator;
CallType (BEAST_MOVE_ARG(F) f, A a = A ())
: m_f (BEAST_MOVE_CAST(F)(f)), m_a (a)
{ }
R operator() (P1 const& p1, P2 const& p2)
{ return (m_f)(p1, p2); }
private:
F m_f;
Allocator m_a;
};
typedef R result_type;
template <typename F>
SharedFunction (F f, A a = A ())
: m_ptr (new (typename CallType <F>::Allocator (a).allocate (1))
CallType <F> (BEAST_MOVE_CAST(F)(f), a))
{ }
SharedFunction (SharedFunction const& other, A)
: m_ptr (other.m_ptr)
{ }
SharedFunction ()
{ }
bool empty () const
{ return m_ptr == nullptr; }
R operator() (P1 const& p1, P2 const& p2) const
{ return (*m_ptr)(p1, p2); }
private:
SharedPtr <Call> m_ptr;
};
//------------------------------------------------------------------------------
template <class R, class P1, class P2, class P3, class A>
class SharedFunction <R (P1, P2, P3), A>
{
public:
struct Call : public SharedObject
{ virtual R operator() (P1 const& p1, P2 const& p2, P3 const& p3) = 0; };
template <typename F>
struct CallType : Call
{
typedef typename A:: template rebind <CallType <F> >::other Allocator;
CallType (BEAST_MOVE_ARG(F) f, A a = A ())
: m_f (BEAST_MOVE_CAST(F)(f)), m_a (a)
{ }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3)
{ return (m_f)(p1, p2, p3); }
private:
F m_f;
Allocator m_a;
};
typedef R result_type;
template <typename F>
SharedFunction (F f, A a = A ())
: m_ptr (new (typename CallType <F>::Allocator (a).allocate (1))
CallType <F> (BEAST_MOVE_CAST(F)(f), a))
{ }
SharedFunction (SharedFunction const& other, A)
: m_ptr (other.m_ptr)
{ }
SharedFunction ()
{ }
bool empty () const
{ return m_ptr == nullptr; }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3) const
{ return (*m_ptr)(p1, p2, p3); }
private:
SharedPtr <Call> m_ptr;
};
//------------------------------------------------------------------------------
template <class R, class P1, class P2, class P3, class P4, class A>
class SharedFunction <R (P1, P2, P3, P4), A>
{
public:
struct Call : public SharedObject
{ virtual R operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) = 0; };
template <typename F>
struct CallType : Call
{
typedef typename A:: template rebind <CallType <F> >::other Allocator;
CallType (BEAST_MOVE_ARG(F) f, A a = A ())
: m_f (BEAST_MOVE_CAST(F)(f)), m_a (a)
{ }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4)
{ return (m_f)(p1, p2, p3, p4); }
private:
F m_f;
Allocator m_a;
};
typedef R result_type;
template <typename F>
SharedFunction (F f, A a = A ())
: m_ptr (new (typename CallType <F>::Allocator (a).allocate (1))
CallType <F> (BEAST_MOVE_CAST(F)(f), a))
{ }
SharedFunction (SharedFunction const& other, A)
: m_ptr (other.m_ptr)
{ }
SharedFunction ()
{ }
bool empty () const
{ return m_ptr == nullptr; }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) const
{ return (*m_ptr)(p1, p2, p3, p4); }
private:
SharedPtr <Call> m_ptr;
};
//------------------------------------------------------------------------------
template <class R, class P1, class P2, class P3, class P4, class P5, class A>
class SharedFunction <R (P1, P2, P3, P4, P5), A>
{
public:
struct Call : public SharedObject
{ virtual R operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5) = 0; };
template <typename F>
struct CallType : Call
{
typedef typename A:: template rebind <CallType <F> >::other Allocator;
CallType (BEAST_MOVE_ARG(F) f, A a = A ())
: m_f (BEAST_MOVE_CAST(F)(f)), m_a (a)
{ }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5)
{ return (m_f)(p1, p2, p3, p4, p5); }
private:
F m_f;
Allocator m_a;
};
typedef R result_type;
template <typename F>
SharedFunction (F f, A a = A ())
: m_ptr (new (typename CallType <F>::Allocator (a).allocate (1))
CallType <F> (BEAST_MOVE_CAST(F)(f), a))
{ }
SharedFunction (SharedFunction const& other, A)
: m_ptr (other.m_ptr)
{ }
SharedFunction ()
{ }
bool empty () const
{ return m_ptr == nullptr; }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5) const
{ return (*m_ptr)(p1, p2, p3, p4, p5); }
private:
SharedPtr <Call> m_ptr;
};
//------------------------------------------------------------------------------
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class A>
class SharedFunction <R (P1, P2, P3, P4, P5, P6), A>
{
public:
struct Call : public SharedObject
{ virtual R operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5, P6 const& p6) = 0; };
template <typename F>
struct CallType : Call
{
typedef typename A:: template rebind <CallType <F> >::other Allocator;
CallType (BEAST_MOVE_ARG(F) f, A a = A ())
: m_f (BEAST_MOVE_CAST(F)(f)), m_a (a)
{ }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5, P6 const& p6)
{ return (m_f)(p1, p2, p3, p4, p5, p6); }
private:
F m_f;
Allocator m_a;
};
typedef R result_type;
template <typename F>
SharedFunction (F f, A a = A ())
: m_ptr (new (typename CallType <F>::Allocator (a).allocate (1))
CallType <F> (BEAST_MOVE_CAST(F)(f), a))
{ }
SharedFunction (SharedFunction const& other, A)
: m_ptr (other.m_ptr)
{ }
SharedFunction ()
{ }
bool empty () const
{ return m_ptr == nullptr; }
R operator() (P1 const& p1, P2 const& p2, P3 const& p3,
P4 const& p4, P5 const& p5, P6 const& p6) const
{ return (*m_ptr)(p1, p2, p3, p4, p5, p6); }
private:
SharedPtr <Call> m_ptr;
};
#endif