$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r84313 - in trunk: boost/asio boost/asio/impl libs/asio/doc libs/asio/example/cpp11/futures
From: chris_at_[hidden]
Date: 2013-05-16 22:35:09
Author: chris_kohlhoff
Date: 2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
New Revision: 84313
URL: http://svn.boost.org/trac/boost/changeset/84313
Log:
Add the asio::use_future special value, which adds first-class support
for returning a C++11 std::future from an asynchronous operation's
initiating function.
To use asio::use_future, pass it to an asynchronous operation instead of
a normal completion handler. For example:
  std::future<std::size_t> length =
    my_socket.async_read_some(my_buffer, asio::use_future);
Where a completion handler signature has the form:
  void handler(error_code ec, result_type result);
the initiating function returns a std::future templated on result_type.
In the above example, this is std::size_t. If the asynchronous operation
fails, the error_code is converted into a system_error exception and
passed back to the caller through the future.
Where a completion handler signature has the form:
  void handler(error_code ec);
the initiating function returns std::future<void>. As above, an error
is passed back in the future as a system_error exception.
Added:
   trunk/boost/asio/impl/use_future.hpp   (contents, props changed)
   trunk/boost/asio/use_future.hpp   (contents, props changed)
   trunk/libs/asio/example/cpp11/futures/
   trunk/libs/asio/example/cpp11/futures/Jamfile   (contents, props changed)
   trunk/libs/asio/example/cpp11/futures/Jamfile.v2   (contents, props changed)
   trunk/libs/asio/example/cpp11/futures/daytime_client.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/asio/doc/Jamfile.v2   |     2 +-                                      
   trunk/libs/asio/doc/examples.qbk |     8 ++++++++                                
   2 files changed, 9 insertions(+), 1 deletions(-)
Added: trunk/boost/asio/impl/use_future.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/impl/use_future.hpp	2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
@@ -0,0 +1,174 @@
+//
+// impl/use_future.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IMPL_USE_FUTURE_HPP
+#define BOOST_ASIO_IMPL_USE_FUTURE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <future>
+#include <boost/asio/async_result.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/handler_type.hpp>
+#include <boost/system/system_error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+  // Completion handler to adapt a promise as a completion handler.
+  template <typename T>
+  class promise_handler
+  {
+  public:
+    // Construct from use_future special value.
+    template <typename Allocator>
+    promise_handler(use_future_t<Allocator> uf)
+      : promise_(std::allocate_shared<std::promise<T> >(
+            uf.get_allocator(), std::allocator_arg, uf.get_allocator()))
+    {
+    }
+
+    void operator()(T t)
+    {
+      promise_->set_value(t);
+    }
+
+    void operator()(const boost::system::error_code& ec, T t)
+    {
+      if (ec)
+        promise_->set_exception(
+            std::make_exception_ptr(
+              boost::system::system_error(ec)));
+      else
+        promise_->set_value(t);
+    }
+
+  //private:
+    std::shared_ptr<std::promise<T> > promise_;
+  };
+
+  // Completion handler to adapt a void promise as a completion handler.
+  template <>
+  class promise_handler<void>
+  {
+  public:
+    // Construct from use_future special value. Used during rebinding.
+    template <typename Allocator>
+    promise_handler(use_future_t<Allocator> uf)
+      : promise_(std::allocate_shared<std::promise<void> >(
+            uf.get_allocator(), std::allocator_arg, uf.get_allocator()))
+    {
+    }
+
+    void operator()()
+    {
+      promise_->set_value();
+    }
+
+    void operator()(const boost::system::error_code& ec)
+    {
+      if (ec)
+        promise_->set_exception(
+            std::make_exception_ptr(
+              boost::system::system_error(ec)));
+      else
+        promise_->set_value();
+    }
+
+  //private:
+    std::shared_ptr<std::promise<void> > promise_;
+  };
+
+  // Ensure any exceptions thrown from the handler are propagated back to the
+  // caller via the future.
+  template <typename Function, typename T>
+  void asio_handler_invoke(Function f, promise_handler<T>* h)
+  {
+    std::shared_ptr<std::promise<T> > p(h->promise_);
+    try
+    {
+      f();
+    }
+    catch (...)
+    {
+      p->set_exception(std::current_exception());
+    }
+  }
+
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+// Handler traits specialisation for promise_handler.
+template <typename T>
+class async_result<detail::promise_handler<T> >
+{
+public:
+  // The initiating function will return a future.
+  typedef std::future<T> type;
+
+  // Constructor creates a new promise for the async operation, and obtains the
+  // corresponding future.
+  explicit async_result(detail::promise_handler<T>& h)
+  {
+    value_ = h.promise_->get_future();
+  }
+
+  // Obtain the future to be returned from the initiating function.
+  type get() { return std::move(value_); }
+
+private:
+  type value_;
+};
+
+// Handler type specialisation for use_future.
+template <typename Allocator, typename ReturnType>
+struct handler_type<use_future_t<Allocator>, ReturnType()>
+{
+  typedef detail::promise_handler<void> type;
+};
+
+// Handler type specialisation for use_future.
+template <typename Allocator, typename ReturnType, typename Arg1>
+struct handler_type<use_future_t<Allocator>, ReturnType(Arg1)>
+{
+  typedef detail::promise_handler<Arg1> type;
+};
+
+// Handler type specialisation for use_future.
+template <typename Allocator, typename ReturnType>
+struct handler_type<use_future_t<Allocator>,
+    ReturnType(boost::system::error_code)>
+{
+  typedef detail::promise_handler<void> type;
+};
+
+// Handler type specialisation for use_future.
+template <typename Allocator, typename ReturnType, typename Arg2>
+struct handler_type<use_future_t<Allocator>,
+    ReturnType(boost::system::error_code, Arg2)>
+{
+  typedef detail::promise_handler<Arg2> type;
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_USE_FUTURE_HPP
Added: trunk/boost/asio/use_future.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/use_future.hpp	2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
@@ -0,0 +1,66 @@
+//
+// use_future.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_USE_FUTURE_HPP
+#define BOOST_ASIO_USE_FUTURE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <memory>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename Allocator = std::allocator<void> >
+class use_future_t
+{
+public:
+  typedef Allocator allocator_type;
+
+  constexpr use_future_t()
+  {
+  }
+
+  explicit use_future_t(const Allocator& allocator)
+    : allocator_(allocator)
+  {
+  }
+
+  template <typename OtherAllocator>
+  use_future_t<OtherAllocator> operator[](const OtherAllocator& allocator) const
+  {
+    return use_future_t<OtherAllocator>(allocator);
+  }
+
+  allocator_type get_allocator() const
+  {
+    return allocator_;
+  }
+
+private:
+  Allocator allocator_;
+};
+
+// A special value, similar to std::nothrow.
+constexpr use_future_t<> use_future;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/use_future.hpp>
+
+#endif // BOOST_ASIO_USE_FUTURE_HPP
Modified: trunk/libs/asio/doc/Jamfile.v2
==============================================================================
--- trunk/libs/asio/doc/Jamfile.v2	(original)
+++ trunk/libs/asio/doc/Jamfile.v2	2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
@@ -31,7 +31,7 @@
   cpp03/iostreams cpp03/local cpp03/multicast cpp03/nonblocking cpp03/porthopper
   cpp03/serialization cpp03/services cpp03/socks4 cpp03/spawn cpp03/ssl
   cpp03/timeouts cpp03/timers cpp03/windows cpp11/allocaton cpp11/buffers
-  cpp11/chat cpp11/echo cpp11/http/server cpp11/spawn ;
+  cpp11/chat cpp11/echo cpp11/futures cpp11/http/server cpp11/spawn ;
 
 for local l in $(example-names)
 {
Modified: trunk/libs/asio/doc/examples.qbk
==============================================================================
--- trunk/libs/asio/doc/examples.qbk	(original)
+++ trunk/libs/asio/doc/examples.qbk	2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
@@ -369,6 +369,14 @@
 * [@boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp] 
 
 
+[heading Futures]
+
+This example demonstrates how to use std::future in conjunction with
+Boost.Asio's asynchronous operations.
+
+* [@boost_asio/example/cpp11/futures/daytime_client.cpp] 
+
+
 [heading HTTP Server]
 
 This example illustrates the use of asio in a simple single-threaded server
Added: trunk/libs/asio/example/cpp11/futures/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/cpp11/futures/Jamfile	2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2003-2012 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)
+#
+
+subproject libs/asio/example/buffers ;
+
+project boost : $(BOOST_ROOT) ;
+
+if $(UNIX)
+{
+  switch $(JAMUNAME)
+  {
+  case SunOS* :
+    {
+      SOCKET_LIBS = <find-library>socket <find-library>nsl ;
+    }
+  }
+}
+
+exe server
+  : <lib>@boost/libs/system/build/boost_system
+    daytime_client.cpp
+  : <include>$(BOOST_ROOT)
+    <include>../../../..
+    <define>BOOST_ALL_NO_LIB=1
+    <threading>multi
+    <mingw><*><find-library>ws2_32
+    <mingw><*><find-library>mswsock
+    $(SOCKET_LIBS)
+  ;
Added: trunk/libs/asio/example/cpp11/futures/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/cpp11/futures/Jamfile.v2	2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2003-2012 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)
+#
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+  lib socket ;
+  lib nsl ;
+}
+else if [ os.name ] = NT
+{
+  lib ws2_32 ;
+  lib mswsock ;
+}
+else if [ os.name ] = HPUX
+{
+  lib ipv6 ;
+}
+
+exe server
+  : daytime_client.cpp
+    /boost/system//boost_system
+  : <define>BOOST_ALL_NO_LIB=1
+    <threading>multi
+    <os>SOLARIS:<library>socket
+    <os>SOLARIS:<library>nsl
+    <os>NT:<define>_WIN32_WINNT=0x0501
+    <os>NT,<toolset>gcc:<library>ws2_32
+    <os>NT,<toolset>gcc:<library>mswsock
+    <os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
+    <os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
+    <os>HPUX:<library>ipv6
+  ;
Added: trunk/libs/asio/example/cpp11/futures/daytime_client.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/example/cpp11/futures/daytime_client.cpp	2013-05-16 22:35:08 EDT (Thu, 16 May 2013)
@@ -0,0 +1,94 @@
+//
+// daytime_client.cpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2012 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)
+//
+
+#include <array>
+#include <future>
+#include <iostream>
+#include <thread>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/use_future.hpp>
+
+using boost::asio::ip::udp;
+
+void get_daytime(boost::asio::io_service& io_service, const char* hostname)
+{
+  try
+  {
+    udp::resolver resolver(io_service);
+
+    std::future<udp::resolver::iterator> iter =
+      resolver.async_resolve(
+          {udp::v4(), hostname, "daytime"},
+          boost::asio::use_future);
+
+    // The async_resolve operation above returns the endpoint iterator as a
+    // future value that is not retrieved ...
+
+    udp::socket socket(io_service, udp::v4());
+
+    std::array<char, 1> send_buf  = {{ 0 }};
+    std::future<std::size_t> send_length =
+      socket.async_send_to(boost::asio::buffer(send_buf),
+          *iter.get(), // ... until here. This call may block.
+          boost::asio::use_future);
+
+    // Do other things here while the send completes.
+
+    send_length.get(); // Blocks until the send is complete. Throws any errors.
+
+    std::array<char, 128> recv_buf;
+    udp::endpoint sender_endpoint;
+    std::future<std::size_t> recv_length =
+      socket.async_receive_from(
+          boost::asio::buffer(recv_buf),
+          sender_endpoint,
+          boost::asio::use_future);
+
+    // Do other things here while the receive completes.
+
+    std::cout.write(
+        recv_buf.data(),
+        recv_length.get()); // Blocks until receive is complete.
+  }
+  catch (std::system_error& e)
+  {
+    std::cerr << e.what() << std::endl;
+  }
+}
+
+int main(int argc, char* argv[])
+{
+  try
+  {
+    if (argc != 2)
+    {
+      std::cerr << "Usage: daytime_client <host>" << std::endl;
+      return 1;
+    }
+
+    // We run the io_service off in its own thread so that it operates
+    // completely asynchronously with respect to the rest of the program.
+    boost::asio::io_service io_service;
+    boost::asio::io_service::work work(io_service);
+    std::thread thread([&io_service](){ io_service.run(); });
+
+    get_daytime(io_service, argv[1]);
+
+    io_service.stop();
+    thread.join();
+  }
+  catch (std::exception& e)
+  {
+    std::cerr << e.what() << std::endl;
+  }
+
+  return 0;
+}