Skip to content

spawn() in boost trunk #12

@snaury

Description

@snaury

There are multiple problems with spawn() in asio with boost 1.55 and trunk

  • spawn.hpp uses defined(BOOST_COROUTINES_UNIDRECT) as a condition, which is a typo, it should be defined(BOOST_COROUTINES_UNIDIRECT) (note that boost trunk no longer even has the old coroutine API)
  • spawn() doesn't work with coroutines v2, and the reason is that it uses push_coroutine<void> for callee_type

The reason push_coroutine<void> doesn't work for callee_type is that there's no context switch on coroutine construction (since push_coroutine expects a value and there's no value until after coroutine is constructed and said value is assigned). So context switch only happens on the line with (*coro)();, and then coroutine runs until ca(); // Yield until coroutine pointer has been initialised. and there's no longer a way for it to continue.

So it seems that you would either need to make callee_type a pull_coroutine<void>, or make use of the fact push_coroutine<void> doesn't context switch on construction, making it quite a bit simpler and better performing:

Index: impl/spawn.hpp
===================================================================
--- impl/spawn.hpp  (revision 86799)
+++ impl/spawn.hpp  (working copy)
@@ -242,7 +242,9 @@
     void operator()(typename basic_yield_context<Handler>::caller_type& ca)
     {
       shared_ptr<spawn_data<Handler, Function> > data(data_);
+#if !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)
       ca(); // Yield until coroutine pointer has been initialised.
+#endif
       const basic_yield_context<Handler> yield(
           data->coro_, ca, data->handler_);
       (data->function_)(yield);
Index: spawn.hpp
===================================================================
--- spawn.hpp   (revision 86799)
+++ spawn.hpp   (working copy)
@@ -58,7 +58,7 @@
    */
 #if defined(GENERATING_DOCUMENTATION)
   typedef implementation_defined callee_type;
-#elif defined(BOOST_COROUTINES_UNIDRECT) || defined(BOOST_COROUTINES_V2)
+#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)
   typedef boost::coroutines::push_coroutine<void> callee_type;
 #else
   typedef boost::coroutines::coroutine<void()> callee_type;
@@ -73,7 +73,7 @@
    */
 #if defined(GENERATING_DOCUMENTATION)
   typedef implementation_defined caller_type;
-#elif defined(BOOST_COROUTINES_UNIDRECT) || defined(BOOST_COROUTINES_V2)
+#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)
   typedef boost::coroutines::pull_coroutine<void> caller_type;
 #else
   typedef boost::coroutines::coroutine<void()>::caller_type caller_type;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions