10ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
20ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// basic_io_object.hpp
30ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// ~~~~~~~~~~~~~~~~~~~
40ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
50ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
60ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
70ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Distributed under the Boost Software License, Version 1.0. (See accompanying
80ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
90ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#ifndef ASIO_BASIC_IO_OBJECT_HPP
120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#define ASIO_BASIC_IO_OBJECT_HPP
130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/config.hpp"
160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/io_service.hpp"
170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/push_options.hpp"
190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace asio {
210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace detail
230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // Type trait used to determine whether a service supports move.
250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename IoObjectService>
260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class service_has_move
270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  private:
290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typedef IoObjectService service_type;
300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typedef typename service_type::implementation_type implementation_type;
310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    template <typename T, typename U>
330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    static auto eval(T* t, U* u) -> decltype(t->move_construct(*u, *u), char());
340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    static char (&eval(...))[2];
350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    static const bool value =
380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      sizeof(service_has_move::eval(
390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        static_cast<service_type*>(0),
400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        static_cast<implementation_type*>(0))) == 1;
410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie/// Base class for all I/O objects.
450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie/**
460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie * @note All I/O objects are non-copyable. However, when using C++0x, certain
470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie * I/O objects do support move construction and move assignment.
480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie */
490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename IoObjectService,
500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    bool Movable = detail::service_has_move<IoObjectService>::value>
510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieclass basic_io_object
520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiepublic:
540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// The type of the service that will be used to provide I/O operations.
550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef IoObjectService service_type;
560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// The underlying implementation type of I/O object.
580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef typename service_type::implementation_type implementation_type;
590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the io_service associated with the object.
610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * This function may be used to obtain the io_service object that the I/O
630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * object uses to dispatch handlers for asynchronous operations.
640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   *
650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @return A reference to the io_service object that the I/O object will use
660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * to dispatch handlers. Ownership is not transferred to the caller.
670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::io_service& get_io_service()
690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return service.get_io_service();
710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprotected:
740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Construct a basic_io_object.
750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Performs:
770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code get_service().construct(get_implementation()); @endcode
780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  explicit basic_io_object(asio::io_service& io_service)
800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : service(asio::use_service<IoObjectService>(io_service))
810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    service.construct(implementation);
830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Protected destructor to prevent deletion through this type.
870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * Performs:
890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @code get_service().destroy(get_implementation()); @endcode
900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ~basic_io_object()
920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    service.destroy(implementation);
940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the service associated with the I/O object.
970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  service_type& get_service()
980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return service;
1000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the service associated with the I/O object.
1030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  const service_type& get_service() const
1040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return service;
1060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// (Deprecated: Use get_service().) The service associated with the I/O
1090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// object.
1100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /**
1110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   * @note Available only for services that do not support movability.
1120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie   */
1130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  service_type& service;
1140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the underlying implementation of the I/O object.
1160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  implementation_type& get_implementation()
1170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return implementation;
1190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// Get the underlying implementation of the I/O object.
1220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  const implementation_type& get_implementation() const
1230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return implementation;
1250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// (Deprecated: Use get_implementation().) The underlying implementation of
1280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  /// the I/O object.
1290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  implementation_type implementation;
1300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprivate:
1320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_io_object(const basic_io_object&);
1330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_io_object& operator=(const basic_io_object&);
1340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
1350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Specialisation for movable objects.
1370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename IoObjectService>
1380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieclass basic_io_object<IoObjectService, true>
1390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiepublic:
1410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef IoObjectService service_type;
1420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typedef typename service_type::implementation_type implementation_type;
1430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::io_service& get_io_service()
1450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return service_->get_io_service();
1470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprotected:
1500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  explicit basic_io_object(asio::io_service& io_service)
1510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : service_(&asio::use_service<IoObjectService>(io_service))
1520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    service_->construct(implementation);
1540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_io_object(basic_io_object&& other)
1570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : service_(&other.get_service())
1580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    service_->move_construct(implementation, other.implementation);
1600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ~basic_io_object()
1630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    service_->destroy(implementation);
1650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_io_object& operator=(basic_io_object&& other)
1680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    service_->move_assign(implementation,
1700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        *other.service_, other.implementation);
1710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    service_ = other.service_;
1720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return *this;
1730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  service_type& get_service()
1760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return *service_;
1780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  const service_type& get_service() const
1810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return *service_;
1830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  implementation_type& get_implementation()
1860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return implementation;
1880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  const implementation_type& get_implementation() const
1910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return implementation;
1930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  implementation_type implementation;
1960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprivate:
1980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  basic_io_object(const basic_io_object&);
1990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  void operator=(const basic_io_object&);
2000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  IoObjectService* service_;
2020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
2030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace asio
2050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/pop_options.hpp"
2070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // ASIO_BASIC_IO_OBJECT_HPP
209