text: //
  // detail/reactive_socket_service_base.hpp
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //
  // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  //
  // Distributed under the Boost Software License, Version 1.0. (See accompanying
  // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  //
  
  #ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
  #define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
  
  #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  # pragma once
  #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  
  #include "asio/detail/config.hpp"
  
  #if !defined(ASIO_HAS_IOCP) \
    && !defined(ASIO_WINDOWS_RUNTIME)
  
  #include "asio/buffer.hpp"
  #include "asio/error.hpp"
  #include "asio/io_service.hpp"
  #include "asio/socket_base.hpp"
  #include "asio/detail/addressof.hpp"
  #include "asio/detail/buffer_sequence_adapter.hpp"
  #include "asio/detail/reactive_null_buffers_op.hpp"
  #include "asio/detail/reactive_socket_recv_op.hpp"
  #include "asio/detail/reactive_socket_recvmsg_op.hpp"
  #include "asio/detail/reactive_socket_send_op.hpp"
  #include "asio/detail/reactor.hpp"
  #include "asio/detail/reactor_op.hpp"
  #include "asio/detail/socket_holder.hpp"
  #include "asio/detail/socket_ops.hpp"
  #include "asio/detail/socket_types.hpp"
  
  #include "asio/detail/push_options.hpp"
  
  namespace clmdep_asio {
  namespace detail {
  
  class reactive_socket_service_base
  {
  public:
    // The native type of a socket.
    typedef socket_type native_handle_type;
  
    // The implementation type of the socket.
    struct base_implementation_type
    {
      // The native socket representation.
      socket_type socket_;
  
      // The current state of the socket.
      socket_ops::state_type state_;
  
      // Per-descriptor data used by the reactor.
      reactor::per_descriptor_data reactor_data_;
    };
  
    // Constructor.
    ASIO_DECL reactive_socket_service_base(
        clmdep_asio::io_service& io_service);
  
    // Destroy all user-defined handler objects owned by the service.
    ASIO_DECL void shutdown_service();
  
    // Construct a new socket implementation.
    ASIO_DECL void construct(base_implementation_type& impl);
  
    // Move-construct a new socket implementation.
    ASIO_DECL void base_move_construct(base_implementation_type& impl,
        base_implementation_type& other_impl);
  
    // Move-assign from another socket implementation.
    ASIO_DECL void base_move_assign(base_implementation_type& impl,
        reactive_socket_service_base& other_service,
        base_implementation_type& other_impl);
  
    // Destroy a socket implementation.
    ASIO_DECL void destroy(base_implementation_type& impl);
  
    // Determine whether the socket is open.
    bool is_open(const base_implementation_type& impl) const
    {
      return impl.socket_ != invalid_socket;
    }
  
    // Destroy a socket implementation.
    ASIO_DECL clmdep_asio::error_code close(
        base_implementation_type& impl, clmdep_asio::error_code& ec);
  
    // Get the native socket representation.
    native_handle_type native_handle(base_implementation_type& impl)
    {
      return impl.socket_;
    }
  
    // Cancel all operations associated with the socket.
    ASIO_DECL clmdep_asio::error_code cancel(
        base_implementation_type& impl, clmdep_asio::error_code& ec);
  
    // Determine whether the socket is at the out-of-band data mark.
    bool at_mark(const base_implementation_type& impl,
        clmdep_asio::error_code& ec) const
    {
      return socket_ops::sockatmark(impl.socket_, ec);
    }
  
    // Determine the number of bytes available for reading.
    std::size_t available(const base_implementation_type& impl,
        clmdep_asio::error_code& ec) const
    {
      return socket_ops::available(impl.socket_, ec);
    }
  
    // Place the socket into the state where it will listen for new connections.
    clmdep_asio::error_code listen(base_implementation_type& impl,
        int backlog, clmdep_asio::error_code& ec)
    {
      socket_ops::listen(impl.socket_, backlog, ec);
      return ec;
    }
  
    // Perform an IO control command on the socket.
    template <typename IO_Control_Command>
    clmdep_asio::error_code io_control(base_implementation_type& impl,
        IO_Control_Command& command, clmdep_asio::error_code& ec)
    {
      socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
          static_cast<ioctl_arg_type*>(command.data()), ec);
      return ec;
    }
  
    // Gets the non-blocking mode of the socket.
    bool non_blocking(const base_implementation_type& impl) const
    {
      return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
    }
  
    // Sets the non-blocking mode of the socket.
    clmdep_asio::error_code non_blocking(base_implementation_type& impl,
        bool mode, clmdep_asio::error_code& ec)
    {
      socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
      return ec;
    }
  
    // Gets the non-blocking mode of the native socket implementation.
    bool native_non_blocking(const base_implementation_type& impl) const
    {
      return (impl.state_ & socket_ops::internal_non_blocking) != 0;
    }
  
    // Sets the non-blocking mode of the native socket implementation.
    clmdep_asio::error_code native_non_blocking(base_implementation_type& impl,
        bool mode, clmdep_asio::error_code& ec)
    {
      socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
      return ec;
    }
  
    // Disable sends or receives on the socket.
    clmdep_asio::error_code shutdown(base_implementation_type& impl,
        socket_base::shutdown_type what, clmdep_asio::error_code& ec)
    {
      socket_ops::shutdown(impl.socket_, what, ec);
      return ec;
    }
  
    // Send the given data to the peer.
    template <typename ConstBufferSequence>
    size_t send(base_implementation_type& impl,
        const ConstBufferSequence& buffers,
        socket_base::message_flags flags, clmdep_asio::error_code& ec)
    {
      buffer_sequence_adapter<clmdep_asio::const_buffer,
          ConstBufferSequence> bufs(buffers);
  
      return socket_ops::sync_send(impl.socket_, impl.state_,
          bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
    }
  
    // Wait until data can be sent without blocking.
    size_t send(base_implementation_type& impl, const null_buffers&,
        socket_base::message_flags, clmdep_asio::error_code& ec)
    {
      // Wait for socket to become ready.
      socket_ops::poll_write(impl.socket_, impl.state_, ec);
  
      return 0;
    }
  
    // Start an asynchronous send. The data being sent must be valid for the
    // lifetime of the asynchronous operation.
    template <typename ConstBufferSequence, typename Handler>
    void async_send(base_implementation_type& impl,
        const ConstBufferSequence& buffers,
        socket_base::message_flags flags, Handler& handler)
    {
      bool is_continuation =
        clmdep_asio_handler_cont_helpers::is_continuation(handler);
  
      // Allocate and construct an operation to wrap the handler.
      typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
      typename op::ptr p = { clmdep_asio::detail::addressof(handler),
        clmdep_asio_handler_alloc_helpers::allocate(
          sizeof(op), handler), 0 };
      p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
  
      ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
  
      start_op(impl, reactor::write_op, p.p, is_continuation, true,
          ((impl.state_ & socket_ops::stream_oriented)
            && buffer_sequence_adapter<clmdep_asio::const_buffer,
              ConstBufferSequence>::all_empty(buffers)));
      p.v = p.p = 0;
    }
  
    // Start an asynchronous wait until data can be sent without blocking.
    template <typename Handler>
    void async_send(base_implementation_type& impl, const null_buffers&,
        socket_base::message_flags, Handler& handler)
    {
      bool is_continuation =
        clmdep_asio_handler_cont_helpers::is_continuation(handler);
  
      // Allocate and construct an operation to wrap the handler.
      typedef reactive_null_buffers_op<Handler> op;
      typename op::ptr p = { clmdep_asio::detail::addressof(handler),
        clmdep_asio_handler_alloc_helpers::allocate(
          sizeof(op), handler), 0 };
      p.p = new (p.v) op(handler);
  
      ASIO_HANDLER_CREATION((p.p, "socket",
            &impl, "async_send(null_buffers)"));
  
      start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
      p.v = p.p = 0;
    }
  
    // Receive some data from the peer. Returns the number of bytes received.
    template <typename MutableBufferSequence>
    size_t receive(base_implementation_type& impl,
        const MutableBufferSequence& buffers,
        socket_base::message_flags flags, clmdep_asio::error_code& ec)
    {
      buffer_sequence_adapter<clmdep_asio::mutable_buffer,
          MutableBufferSequence> bufs(buffers);
  
      return socket_ops::sync_recv(impl.socket_, impl.state_,
          bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
    }
  
    // Wait until data can be received without blocking.
    size_t receive(base_implementation_type& impl, const null_buffers&,
        socket_base::message_flags, clmdep_asio::error_code& ec)
    {
      // Wait for socket to become ready.
      socket_ops::poll_read(impl.socket_, impl.state_, ec);
  
      return 0;
    }
  
    // Start an asynchronous receive. The buffer for the data being received
    // must be valid for the lifetime of the asynchronous operation.
    template <typename MutableBufferSequence, typename Handler>
    void async_receive(base_implementation_type& impl,
        const MutableBufferSequence& buffers,
        socket_base::message_flags flags, Handler& handler)
    {
      bool is_continuation =
        clmdep_asio_handler_cont_helpers::is_continuation(handler);
  
      // Allocate and construct an operation to wrap the handler.
      typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op;
      typename op::ptr p = { clmdep_asio::detail::addressof(handler),
        clmdep_asio_handler_alloc_helpers::allocate(
          sizeof(op), handler), 0 };
      p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
  
      ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
  
      start_op(impl,
          (flags & socket_base::message_out_of_band)
            ? reactor::except_op : reactor::read_op,
          p.p, is_continuation,
          (flags & socket_base::message_out_of_band) == 0,
          ((impl.state_ & socket_ops::stream_oriented)
            && buffer_sequence_adapter<clmdep_asio::mutable_buffer,
              MutableBufferSequence>::all_empty(buffers)));
      p.v = p.p = 0;
    }
  
    // Wait until data can be received without blocking.
    template <typename Handler>
    void async_receive(base_implementation_type& impl, const null_buffers&,
        socket_base::message_flags flags, Handler& handler)
    {
      bool is_continuation =
        clmdep_asio_handler_cont_helpers::is_continuation(handler);
  
      // Allocate and construct an operation to wrap the handler.
      typedef reactive_null_buffers_op<Handler> op;
      typename op::ptr p = { clmdep_asio::detail::addressof(handler),
        clmdep_asio_handler_alloc_helpers::allocate(
          sizeof(op), handler), 0 };
      p.p = new (p.v) op(handler);
  
      ASIO_HANDLER_CREATION((p.p, "socket",
            &impl, "async_receive(null_buffers)"));
  
      start_op(impl,
          (flags & socket_base::message_out_of_band)
            ? reactor::except_op : reactor::read_op,
          p.p, is_continuation, false, false);
      p.v = p.p = 0;
    }
  
    // Receive some data with associated flags. Returns the number of bytes
    // received.
    template <typename MutableBufferSequence>
    size_t receive_with_flags(base_implementation_type& impl,
        const MutableBufferSequence& buffers,
        socket_base::message_flags in_flags,
        socket_base::message_flags& out_flags, clmdep_asio::error_code& ec)
    {
      buffer_sequence_adapter<clmdep_asio::mutable_buffer,
          MutableBufferSequence> bufs(buffers);
  
      return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
          bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
    }
  
    // Wait until data can be received without blocking.
    size_t receive_with_flags(base_implementation_type& impl,
        const null_buffers&, socket_base::message_flags,
        socket_base::message_flags& out_flags, clmdep_asio::error_code& ec)
    {
      // Wait for socket to become ready.
      socket_ops::poll_read(impl.socket_, impl.state_, ec);
  
      // Clear out_flags, since we cannot give it any other sensible value when
      // performing a null_buffers operation.
      out_flags = 0;
  
      return 0;
    }
  
    // Start an asynchronous receive. The buffer for the data being received
    // must be valid for the lifetime of the asynchronous operation.
    template <typename MutableBufferSequence, typename Handler>
    void async_receive_with_flags(base_implementation_type& impl,
        const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
        socket_base::message_flags& out_flags, Handler& handler)
    {
      bool is_continuation =
        clmdep_asio_handler_cont_helpers::is_continuation(handler);
  
      // Allocate and construct an operation to wrap the handler.
      typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op;
      typename op::ptr p = { clmdep_asio::detail::addressof(handler),
        clmdep_asio_handler_alloc_helpers::allocate(
          sizeof(op), handler), 0 };
      p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
  
      ASIO_HANDLER_CREATION((p.p, "socket",
            &impl, "async_receive_with_flags"));
  
      start_op(impl,
          (in_flags & socket_base::message_out_of_band)
            ? reactor::except_op : reactor::read_op,
          p.p, is_continuation,
          (in_flags & socket_base::message_out_of_band) == 0, false);
      p.v = p.p = 0;
    }
  
    // Wait until data can be received without blocking.
    template <typename Handler>
    void async_receive_with_flags(base_implementation_type& impl,
        const null_buffers&, socket_base::message_flags in_flags,
        socket_base::message_flags& out_flags, Handler& handler)
    {
      bool is_continuation =
        clmdep_asio_handler_cont_helpers::is_continuation(handler);
  
      // Allocate and construct an operation to wrap the handler.
      typedef reactive_null_buffers_op<Handler> op;
      typename op::ptr p = { clmdep_asio::detail::addressof(handler),
        clmdep_asio_handler_alloc_helpers::allocate(
          sizeof(op), handler), 0 };
      p.p = new (p.v) op(handler);
  
      ASIO_HANDLER_CREATION((p.p, "socket", &impl,
            "async_receive_with_flags(null_buffers)"));
  
      // Clear out_flags, since we cannot give it any other sensible value when
      // performing a null_buffers operation.
      out_flags = 0;
  
      start_op(impl,
          (in_flags & socket_base::message_out_of_band)
            ? reactor::except_op : reactor::read_op,
          p.p, is_continuation, false, false);
      p.v = p.p = 0;
    }
  
  protected:
    // Open a new socket implementation.
    ASIO_DECL clmdep_asio::error_code do_open(
        base_implementation_type& impl, int af,
        int type, int protocol, clmdep_asio::error_code& ec);
  
    // Assign a native socket to a socket implementation.
    ASIO_DECL clmdep_asio::error_code do_assign(
        base_implementation_type& impl, int type,
        const native_handle_type& native_socket, clmdep_asio::error_code& ec);
  
    // Start the asynchronous read or write operation.
    ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
        reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
  
    // Start the asynchronous accept operation.
    ASIO_DECL void start_accept_op(base_implementation_type& impl,
        reactor_op* op, bool is_continuation, bool peer_is_open);
  
    // Start the asynchronous connect operation.
    ASIO_DECL void start_connect_op(base_implementation_type& impl,
        reactor_op* op, bool is_continuation,
        const socket_addr_type* addr, size_t addrlen);
  
    // The selector that performs event demultiplexing for the service.
    reactor& reactor_;
  };
  
  } // namespace detail
  } // namespace clmdep_asio
  
  #include "asio/detail/pop_options.hpp"
  
  #if defined(ASIO_HEADER_ONLY)
  # include "asio/detail/impl/reactive_socket_service_base.ipp"
  #endif // defined(ASIO_HEADER_ONLY)
  
  #endif // !defined(ASIO_HAS_IOCP)
         //   && !defined(ASIO_WINDOWS_RUNTIME)
  
  #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
  