$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r84346 - in trunk: boost boost/asio libs/asio/doc libs/asio/example/cpp03/http/server4 libs/asio/test
From: chris_at_[hidden]
Date: 2013-05-18 07:55:01
Author: chris_kohlhoff
Date: 2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
New Revision: 84346
URL: http://svn.boost.org/trac/boost/changeset/84346
Log:
Remove the stackless coroutine class and macros from the HTTP server 4
example, and instead make them a part of Asio's documented interface.
Added:
   trunk/boost/asio/coroutine.hpp   (contents, props changed)
   trunk/boost/asio/unyield.hpp   (contents, props changed)
   trunk/boost/asio/yield.hpp   (contents, props changed)
   trunk/libs/asio/test/coroutine.cpp   (contents, props changed)
Removed:
   trunk/libs/asio/example/cpp03/http/server4/coroutine.hpp
   trunk/libs/asio/example/cpp03/http/server4/unyield.hpp
   trunk/libs/asio/example/cpp03/http/server4/yield.hpp
Text files modified: 
   trunk/boost/asio.hpp                                          |     1 +                                       
   trunk/libs/asio/doc/examples.qbk                              |     3 ---                                     
   trunk/libs/asio/doc/reference.xsl                             |     5 ++++-                                   
   trunk/libs/asio/example/cpp03/http/server4/request_parser.cpp |     6 ++++--                                  
   trunk/libs/asio/example/cpp03/http/server4/request_parser.hpp |     4 ++--                                    
   trunk/libs/asio/example/cpp03/http/server4/server.cpp         |     6 ++++--                                  
   trunk/libs/asio/example/cpp03/http/server4/server.hpp         |     3 +--                                     
   trunk/libs/asio/test/Jamfile                                  |     1 +                                       
   trunk/libs/asio/test/Jamfile.v2                               |     2 ++                                      
   9 files changed, 19 insertions(+), 12 deletions(-)
Modified: trunk/boost/asio.hpp
==============================================================================
--- trunk/boost/asio.hpp	(original)
+++ trunk/boost/asio.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -41,6 +41,7 @@
 #include <boost/asio/buffers_iterator.hpp>
 #include <boost/asio/completion_condition.hpp>
 #include <boost/asio/connect.hpp>
+#include <boost/asio/coroutine.hpp>
 #include <boost/asio/datagram_socket_service.hpp>
 #include <boost/asio/deadline_timer_service.hpp>
 #include <boost/asio/deadline_timer.hpp>
Added: trunk/boost/asio/coroutine.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/coroutine.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -0,0 +1,330 @@
+//
+// coroutine.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 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_COROUTINE_HPP
+#define BOOST_ASIO_COROUTINE_HPP
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class coroutine_ref;
+
+} // namespace detail
+
+/// Provides support for implementing stackless coroutines.
+/**
+ * The @c coroutine class may be used to implement stackless coroutines. The
+ * class itself is used to store the current state of the coroutine.
+ *
+ * Coroutines are copy-constructible and assignable, and the space overhead is
+ * a single int. They can be used as a base class:
+ *
+ * @code class session : coroutine
+ * {
+ *   ...
+ * }; @endcode
+ *
+ * or as a data member:
+ *
+ * @code class session
+ * {
+ *   ...
+ *   coroutine coro_;
+ * }; @endcode
+ *
+ * or even bound in as a function argument using lambdas or @c bind(). The
+ * important thing is that as the application maintains a copy of the object
+ * for as long as the coroutine must be kept alive.
+ *
+ * @par Pseudo-keywords
+ *
+ * A coroutine is used in conjunction with certain "pseudo-keywords", which
+ * are implemented as macros. These macros are defined by a header file:
+ *
+ * @code #include <boost/asio/yield.hpp>@endcode
+ *
+ * and may conversely be undefined as follows:
+ *
+ * @code #include <boost/asio/unyield.hpp>@endcode
+ *
+ * <b>reenter</b>
+ *
+ * The @c reenter macro is used to define the body of a coroutine. It takes a
+ * single argument: a pointer or reference to a coroutine object. For example,
+ * if the base class is a coroutine object you may write:
+ *
+ * @code reenter (this)
+ * {
+ *   ... coroutine body ...
+ * } @endcode
+ *
+ * and if a data member or other variable you can write:
+ *
+ * @code reenter (coro_)
+ * {
+ *   ... coroutine body ...
+ * } @endcode
+ *
+ * When @c reenter is executed at runtime, control jumps to the location of the
+ * last @c yield or @c fork.
+ *
+ * The coroutine body may also be a single statement, such as:
+ *
+ * @code reenter (this) for (;;)
+ * {
+ *   ...
+ * } @endcode
+ *
+ * @b Limitation: The @c reenter macro is implemented using a switch. This
+ * means that you must take care when using local variables within the
+ * coroutine body. The local variable is not allowed in a position where
+ * reentering the coroutine could bypass the variable definition.
+ *
+ * <b>yield <em>statement</em></b>
+ *
+ * This form of the @c yield keyword is often used with asynchronous operations:
+ *
+ * @code yield socket_->async_read_some(buffer(*buffer_), *this); @endcode
+ *
+ * This divides into four logical steps:
+ *
+ * @li @c yield saves the current state of the coroutine.
+ * @li The statement initiates the asynchronous operation.
+ * @li The resume point is defined immediately following the statement.
+ * @li Control is transferred to the end of the coroutine body.
+ *
+ * When the asynchronous operation completes, the function object is invoked
+ * and @c reenter causes control to transfer to the resume point. It is
+ * important to remember to carry the coroutine state forward with the
+ * asynchronous operation. In the above snippet, the current class is a
+ * function object object with a coroutine object as base class or data member.
+ *
+ * The statement may also be a compound statement, and this permits us to
+ * define local variables with limited scope:
+ *
+ * @code yield
+ * {
+ *   mutable_buffers_1 b = buffer(*buffer_);
+ *   socket_->async_read_some(b, *this);
+ * } @endcode
+ *
+ * <b>yield return <em>expression</em> ;</b>
+ *
+ * This form of @c yield is often used in generators or coroutine-based parsers.
+ * For example, the function object:
+ *
+ * @code struct interleave : coroutine
+ * {
+ *   istream& is1;
+ *   istream& is2;
+ *   char operator()(char c)
+ *   {
+ *     reenter (this) for (;;)
+ *     {
+ *       yield return is1.get();
+ *       yield return is2.get();
+ *     }
+ *   }
+ * }; @endcode
+ *
+ * defines a trivial coroutine that interleaves the characters from two input
+ * streams.
+ *
+ * This type of @c yield divides into three logical steps:
+ *
+ * @li @c yield saves the current state of the coroutine.
+ * @li The resume point is defined immediately following the semicolon.
+ * @li The value of the expression is returned from the function.
+ *
+ * <b>yield ;</b>
+ *
+ * This form of @c yield is equivalent to the following steps:
+ *
+ * @li @c yield saves the current state of the coroutine.
+ * @li The resume point is defined immediately following the semicolon.
+ * @li Control is transferred to the end of the coroutine body.
+ *
+ * This form might be applied when coroutines are used for cooperative
+ * threading and scheduling is explicitly managed. For example:
+ *
+ * @code struct task : coroutine
+ * {
+ *   ...
+ *   void operator()()
+ *   {
+ *     reenter (this)
+ *     {
+ *       while (... not finished ...)
+ *       {
+ *         ... do something ...
+ *         yield;
+ *         ... do some more ...
+ *         yield;
+ *       }
+ *     }
+ *   }
+ *   ...
+ * };
+ * ...
+ * task t1, t2;
+ * for (;;)
+ * {
+ *   t1();
+ *   t2();
+ * } @endcode
+ *
+ * <b>yield break ;</b>
+ *
+ * The final form of @c yield is used to explicitly terminate the coroutine.
+ * This form is comprised of two steps:
+ *
+ * @li @c yield sets the coroutine state to indicate termination.
+ * @li Control is transferred to the end of the coroutine body.
+ *
+ * Once terminated, calls to is_complete() return true and the coroutine cannot
+ * be reentered.
+ *
+ * Note that a coroutine may also be implicitly terminated if the coroutine
+ * body is exited without a yield, e.g. by return, throw or by running to the
+ * end of the body.
+ *
+ * <b>fork <em>statement</em></b>
+ *
+ * The @c fork pseudo-keyword is used when "forking" a coroutine, i.e. splitting
+ * it into two (or more) copies. One use of @c fork is in a server, where a new
+ * coroutine is created to handle each client connection:
+ * 
+ * @code reenter (this)
+ * {
+ *   do
+ *   {
+ *     socket_.reset(new tcp::socket(io_service_));
+ *     yield acceptor->async_accept(*socket_, *this);
+ *     fork server(*this)();
+ *   } while (is_parent());
+ *   ... client-specific handling follows ...
+ * } @endcode
+ * 
+ * The logical steps involved in a @c fork are:
+ * 
+ * @li @c fork saves the current state of the coroutine.
+ * @li The statement creates a copy of the coroutine and either executes it
+ *     immediately or schedules it for later execution.
+ * @li The resume point is defined immediately following the semicolon.
+ * @li For the "parent", control immediately continues from the next line.
+ *
+ * The functions is_parent() and is_child() can be used to differentiate
+ * between parent and child. You would use these functions to alter subsequent
+ * control flow.
+ *
+ * Note that @c fork doesn't do the actual forking by itself. It is the
+ * application's responsibility to create a clone of the coroutine and call it.
+ * The clone can be called immediately, as above, or scheduled for delayed
+ * execution using something like io_service::post().
+ *
+ * @par Alternate macro names
+ *
+ * If preferred, an application can use macro names that follow a more typical
+ * naming convention, rather than the pseudo-keywords. These are:
+ *
+ * @li @c BOOST_ASIO_CORO_REENTER instead of @c reenter
+ * @li @c BOOST_ASIO_CORO_YIELD instead of @c yield
+ * @li @c BOOST_ASIO_CORO_FORK instead of @c fork
+ */
+class coroutine
+{
+public:
+  /// Constructs a coroutine in its initial state.
+  coroutine() : value_(0) {}
+
+  /// Returns true if the coroutine is the child of a fork.
+  bool is_child() const { return value_ < 0; }
+
+  /// Returns true if the coroutine is the parent of a fork.
+  bool is_parent() const { return !is_child(); }
+
+  /// Returns true if the coroutine has reached its terminal state.
+  bool is_complete() const { return value_ == -1; }
+
+private:
+  friend class detail::coroutine_ref;
+  int value_;
+};
+
+
+namespace detail {
+
+class coroutine_ref
+{
+public:
+  coroutine_ref(coroutine& c) : value_(c.value_), modified_(false) {}
+  coroutine_ref(coroutine* c) : value_(c->value_), modified_(false) {}
+  ~coroutine_ref() { if (!modified_) value_ = -1; }
+  operator int() const { return value_; }
+  int& operator=(int v) { modified_ = true; return value_ = v; }
+private:
+  void operator=(const coroutine_ref&);
+  int& value_;
+  bool modified_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#define BOOST_ASIO_CORO_REENTER(c) \
+  switch (::boost::asio::detail::coroutine_ref _coro_value = c) \
+    case -1: if (_coro_value) \
+    { \
+      goto terminate_coroutine; \
+      terminate_coroutine: \
+      _coro_value = -1; \
+      goto bail_out_of_coroutine; \
+      bail_out_of_coroutine: \
+      break; \
+    } \
+    else case 0:
+
+#define BOOST_ASIO_CORO_YIELD_IMPL(n) \
+  for (_coro_value = (n);;) \
+    if (_coro_value == 0) \
+    { \
+      case (n): ; \
+      break; \
+    } \
+    else \
+      switch (_coro_value ? 0 : 1) \
+        for (;;) \
+          case -1: if (_coro_value) \
+            goto terminate_coroutine; \
+          else for (;;) \
+            case 1: if (_coro_value) \
+              goto bail_out_of_coroutine; \
+            else case 0:
+
+#define BOOST_ASIO_CORO_FORK_IMPL(n) \
+  for (_coro_value = -(n);; _coro_value = (n)) \
+    if (_coro_value == (n)) \
+    { \
+      case -(n): ; \
+      break; \
+    } \
+    else
+
+#if defined(_MSC_VER)
+# define BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD_IMPL(__COUNTER__ + 1)
+# define BOOST_ASIO_CORO_FORK BOOST_ASIO_CORO_FORK_IMPL(__COUNTER__ + 1)
+#else // defined(_MSC_VER)
+# define BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD_IMPL(__LINE__)
+# define BOOST_ASIO_CORO_FORK BOOST_ASIO_CORO_FORK_IMPL(__LINE__)
+#endif // defined(_MSC_VER)
+
+#endif // BOOST_ASIO_COROUTINE_HPP
Added: trunk/boost/asio/unyield.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/unyield.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -0,0 +1,21 @@
+//
+// unyield.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 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)
+//
+
+#ifdef reenter
+# undef reenter
+#endif
+
+#ifdef yield
+# undef yield
+#endif
+
+#ifdef fork
+# undef fork
+#endif
Added: trunk/boost/asio/yield.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/yield.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -0,0 +1,23 @@
+//
+// yield.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2013 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 "coroutine.hpp"
+
+#ifndef reenter
+# define reenter(c) BOOST_ASIO_CORO_REENTER(c)
+#endif
+
+#ifndef yield
+# define yield BOOST_ASIO_CORO_YIELD
+#endif
+
+#ifndef fork
+# define fork BOOST_ASIO_CORO_FORK
+#endif
Modified: trunk/libs/asio/doc/examples.qbk
==============================================================================
--- trunk/libs/asio/doc/examples.qbk	(original)
+++ trunk/libs/asio/doc/examples.qbk	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -162,7 +162,6 @@
 
 A single-threaded HTTP server implemented using stackless coroutines.
 
-* [@boost_asio/example/cpp03/http/server4/coroutine.hpp]
 * [@boost_asio/example/cpp03/http/server4/file_handler.cpp]
 * [@boost_asio/example/cpp03/http/server4/file_handler.hpp]
 * [@boost_asio/example/cpp03/http/server4/header.hpp]
@@ -176,8 +175,6 @@
 * [@boost_asio/example/cpp03/http/server4/request_parser.hpp]
 * [@boost_asio/example/cpp03/http/server4/server.cpp]
 * [@boost_asio/example/cpp03/http/server4/server.hpp]
-* [@boost_asio/example/cpp03/http/server4/unyield.hpp]
-* [@boost_asio/example/cpp03/http/server4/yield.hpp]
 
 
 [heading ICMP]
Modified: trunk/libs/asio/doc/reference.xsl
==============================================================================
--- trunk/libs/asio/doc/reference.xsl	(original)
+++ trunk/libs/asio/doc/reference.xsl	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -424,7 +424,10 @@
 </xsl:template>
 
 
-<xsl:template match="emphasis" mode="markup">[*<xsl:value-of select="."/>]</xsl:template>
+<xsl:template match="bold" mode="markup">[*<xsl:apply-templates mode="markup"/>]</xsl:template>
+
+
+<xsl:template match="emphasis" mode="markup">['<xsl:apply-templates mode="markup"/>]</xsl:template>
 
 
 <xsl:template match="parameterlist" mode="markup">
Deleted: trunk/libs/asio/example/cpp03/http/server4/coroutine.hpp
==============================================================================
--- trunk/libs/asio/example/cpp03/http/server4/coroutine.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
+++ (empty file)
@@ -1,87 +0,0 @@
-//
-// coroutine.hpp
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2013 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 COROUTINE_HPP
-#define COROUTINE_HPP
-
-class coroutine
-{
-public:
-  coroutine() : value_(0) {}
-  bool is_child() const { return value_ < 0; }
-  bool is_parent() const { return !is_child(); }
-  bool is_complete() const { return value_ == -1; }
-private:
-  friend class coroutine_ref;
-  int value_;
-};
-
-class coroutine_ref
-{
-public:
-  coroutine_ref(coroutine& c) : value_(c.value_), modified_(false) {}
-  coroutine_ref(coroutine* c) : value_(c->value_), modified_(false) {}
-  ~coroutine_ref() { if (!modified_) value_ = -1; }
-  operator int() const { return value_; }
-  int& operator=(int v) { modified_ = true; return value_ = v; }
-private:
-  void operator=(const coroutine_ref&);
-  int& value_;
-  bool modified_;
-};
-
-#define CORO_REENTER(c) \
-  switch (coroutine_ref _coro_value = c) \
-    case -1: if (_coro_value) \
-    { \
-      goto terminate_coroutine; \
-      terminate_coroutine: \
-      _coro_value = -1; \
-      goto bail_out_of_coroutine; \
-      bail_out_of_coroutine: \
-      break; \
-    } \
-    else case 0:
-
-#define CORO_YIELD_IMPL(n) \
-  for (_coro_value = (n);;) \
-    if (_coro_value == 0) \
-    { \
-      case (n): ; \
-      break; \
-    } \
-    else \
-      switch (_coro_value ? 0 : 1) \
-        for (;;) \
-          case -1: if (_coro_value) \
-            goto terminate_coroutine; \
-          else for (;;) \
-            case 1: if (_coro_value) \
-              goto bail_out_of_coroutine; \
-            else case 0:
-
-#define CORO_FORK_IMPL(n) \
-  for (_coro_value = -(n);; _coro_value = (n)) \
-    if (_coro_value == (n)) \
-    { \
-      case -(n): ; \
-      break; \
-    } \
-    else
-
-#if defined(_MSC_VER)
-# define CORO_YIELD CORO_YIELD_IMPL(__COUNTER__ + 1)
-# define CORO_FORK CORO_FORK_IMPL(__COUNTER__ + 1)
-#else // defined(_MSC_VER)
-# define CORO_YIELD CORO_YIELD_IMPL(__LINE__)
-# define CORO_FORK CORO_FORK_IMPL(__LINE__)
-#endif // defined(_MSC_VER)
-
-#endif // COROUTINE_HPP
Modified: trunk/libs/asio/example/cpp03/http/server4/request_parser.cpp
==============================================================================
--- trunk/libs/asio/example/cpp03/http/server4/request_parser.cpp	(original)
+++ trunk/libs/asio/example/cpp03/http/server4/request_parser.cpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -17,7 +17,8 @@
 namespace http {
 namespace server4 {
 
-#include "yield.hpp" // Enable the pseudo-keywords reenter, yield and fork.
+// Enable the pseudo-keywords reenter, yield and fork.
+#include <boost/asio/yield.hpp>
 
 std::string request_parser::content_length_name_ = "Content-Length";
 
@@ -175,7 +176,8 @@
   return true;
 }
 
-#include "unyield.hpp" // Disable the pseudo-keywords reenter, yield and fork.
+// Disable the pseudo-keywords reenter, yield and fork.
+#include <boost/asio/unyield.hpp>
 
 bool request_parser::is_char(int c)
 {
Modified: trunk/libs/asio/example/cpp03/http/server4/request_parser.hpp
==============================================================================
--- trunk/libs/asio/example/cpp03/http/server4/request_parser.hpp	(original)
+++ trunk/libs/asio/example/cpp03/http/server4/request_parser.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -14,7 +14,7 @@
 #include <string>
 #include <boost/logic/tribool.hpp>
 #include <boost/tuple/tuple.hpp>
-#include "coroutine.hpp"
+#include <boost/asio/coroutine.hpp>
 
 namespace http {
 namespace server4 {
@@ -22,7 +22,7 @@
 struct request;
 
 /// Parser for incoming requests.
-class request_parser : coroutine
+class request_parser : boost::asio::coroutine
 {
 public:
   /// Parse some data. The tribool return value is true when a complete request
Modified: trunk/libs/asio/example/cpp03/http/server4/server.cpp
==============================================================================
--- trunk/libs/asio/example/cpp03/http/server4/server.cpp	(original)
+++ trunk/libs/asio/example/cpp03/http/server4/server.cpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -25,7 +25,8 @@
   acceptor_.reset(new tcp::acceptor(io_service, *resolver.resolve(query)));
 }
 
-#include "yield.hpp" // Enable the pseudo-keywords reenter, yield and fork.
+// Enable the pseudo-keywords reenter, yield and fork.
+#include <boost/asio/yield.hpp>
 
 void server::operator()(boost::system::error_code ec, std::size_t length)
 {
@@ -113,7 +114,8 @@
   // will be destroyed automatically after this function call returns.
 }
 
-#include "unyield.hpp" // Disable the pseudo-keywords reenter, yield and fork.
+// Disable the pseudo-keywords reenter, yield and fork.
+#include <boost/asio/unyield.hpp>
 
 } // namespace server4
 } // namespace http
Modified: trunk/libs/asio/example/cpp03/http/server4/server.hpp
==============================================================================
--- trunk/libs/asio/example/cpp03/http/server4/server.hpp	(original)
+++ trunk/libs/asio/example/cpp03/http/server4/server.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -16,7 +16,6 @@
 #include <boost/array.hpp>
 #include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
-#include "coroutine.hpp"
 #include "request_parser.hpp"
 
 namespace http {
@@ -26,7 +25,7 @@
 struct reply;
 
 /// The top-level coroutine of the HTTP server.
-class server : coroutine
+class server : boost::asio::coroutine
 {
 public:
   /// Construct the server to listen on the specified TCP address and port, and
Deleted: trunk/libs/asio/example/cpp03/http/server4/unyield.hpp
==============================================================================
--- trunk/libs/asio/example/cpp03/http/server4/unyield.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
+++ (empty file)
@@ -1,21 +0,0 @@
-//
-// unyield.hpp
-// ~~~~~~~~~~~
-//
-// Copyright (c) 2003-2013 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)
-//
-
-#ifdef reenter
-# undef reenter
-#endif
-
-#ifdef yield
-# undef yield
-#endif
-
-#ifdef fork
-# undef fork
-#endif
Deleted: trunk/libs/asio/example/cpp03/http/server4/yield.hpp
==============================================================================
--- trunk/libs/asio/example/cpp03/http/server4/yield.hpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
+++ (empty file)
@@ -1,23 +0,0 @@
-//
-// yield.hpp
-// ~~~~~~~~~
-//
-// Copyright (c) 2003-2013 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 "coroutine.hpp"
-
-#ifndef reenter
-# define reenter(c) CORO_REENTER(c)
-#endif
-
-#ifndef yield
-# define yield CORO_YIELD
-#endif
-
-#ifndef fork
-# define fork CORO_FORK
-#endif
Modified: trunk/libs/asio/test/Jamfile
==============================================================================
--- trunk/libs/asio/test/Jamfile	(original)
+++ trunk/libs/asio/test/Jamfile	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -54,6 +54,7 @@
   [ run buffers_iterator.cpp <template>asio_unit_test ]
   [ run completion_condition.cpp <template>asio_unit_test ]
   [ run connect.cpp <template>asio_unit_test ]
+  [ run coroutine.cpp <template>asio_unit_test ]
   [ run datagram_socket_service.cpp <template>asio_unit_test ]
   [ run deadline_timer_service.cpp <template>asio_unit_test ]
   [ run deadline_timer.cpp <template>asio_unit_test ]
Modified: trunk/libs/asio/test/Jamfile.v2
==============================================================================
--- trunk/libs/asio/test/Jamfile.v2	(original)
+++ trunk/libs/asio/test/Jamfile.v2	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -93,6 +93,8 @@
   [ link completion_condition.cpp : $(USE_SELECT) : completion_condition_select ]
   [ link connect.cpp ]
   [ link connect.cpp : $(USE_SELECT) : connect_select ]
+  [ link coroutine.cpp ]
+  [ link coroutine.cpp : $(USE_SELECT) : coroutine_select ]
   [ link datagram_socket_service.cpp ]
   [ link datagram_socket_service.cpp : $(USE_SELECT) : datagram_socket_service_select ]
   [ link deadline_timer_service.cpp ]
Added: trunk/libs/asio/test/coroutine.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/asio/test/coroutine.cpp	2013-05-18 07:54:59 EDT (Sat, 18 May 2013)
@@ -0,0 +1,112 @@
+//
+// coroutine.cpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 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)
+//
+
+// Disable autolinking for unit tests.
+#if !defined(BOOST_ALL_NO_LIB)
+#define BOOST_ALL_NO_LIB 1
+#endif // !defined(BOOST_ALL_NO_LIB)
+
+// Test that header file is self-contained.
+#include <boost/asio/coroutine.hpp>
+
+#include "unit_test.hpp"
+
+// Must come after all other headers.
+#include <boost/asio/yield.hpp>
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes via yield break.
+
+void yield_break_coro(boost::asio::coroutine& coro)
+{
+  reenter (coro)
+  {
+    yield return;
+    yield break;
+  }
+}
+
+void yield_break_test()
+{
+  boost::asio::coroutine coro;
+  BOOST_ASIO_CHECK(!coro.is_complete());
+  yield_break_coro(coro);
+  BOOST_ASIO_CHECK(!coro.is_complete());
+  yield_break_coro(coro);
+  BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes via return.
+
+void return_coro(boost::asio::coroutine& coro)
+{
+  reenter (coro)
+  {
+    return;
+  }
+}
+
+void return_test()
+{
+  boost::asio::coroutine coro;
+  return_coro(coro);
+  BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes via exception.
+
+void exception_coro(boost::asio::coroutine& coro)
+{
+  reenter (coro)
+  {
+    throw 1;
+  }
+}
+
+void exception_test()
+{
+  boost::asio::coroutine coro;
+  try { exception_coro(coro); } catch (int) {}
+  BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+// Coroutine completes by falling off the end.
+
+void fall_off_end_coro(boost::asio::coroutine& coro)
+{
+  reenter (coro)
+  {
+  }
+}
+
+void fall_off_end_test()
+{
+  boost::asio::coroutine coro;
+  fall_off_end_coro(coro);
+  BOOST_ASIO_CHECK(coro.is_complete());
+}
+
+//------------------------------------------------------------------------------
+
+BOOST_ASIO_TEST_SUITE
+(
+  "coroutine",
+  BOOST_ASIO_TEST_CASE(yield_break_test)
+  BOOST_ASIO_TEST_CASE(return_test)
+  BOOST_ASIO_TEST_CASE(exception_test)
+  BOOST_ASIO_TEST_CASE(fall_off_end_test)
+)