Boost logo

Boost :

From: atkinson julian (julian.atkinson71_at_[hidden])
Date: 2008-07-22 16:56:35


Hi, the combination of asio and coroutines would seem to represent a little
bit of magic (layering a linear code model over an async event framework and
without the attendant issues involved in multithreading). However the
coroutine library seems to be exception throwing in an unanticipated way
when performing a wait on a future<> during the execution of an asio async
operation. I am following the documention and am reasonably familiar with
asio from other projects - but have only just worked through some of the
examples from the coroutines documention. i am using the vault freeze
version of coroutines from 2006 - i understand from perusing these lists
that the library author is currently rewritting boost::coroutine around a
continuation framework to simplify and in the hope that the library may be
an official boost inclusion. Much kudos for contributing to c++ in a
significant way ;-)

the documentation seems to have some errors
    http://www.crystalclearsoftware.com/soc/coroutine/coroutine/asio.html
- guidance is given to use shared_coroutine in preference to coroutine in
asio context although this is not present in the example
- asio uses the boost::system error classes in the boost namespace when not
freestanding
- the example calls wait() on source which is a socket type rather than a
future

I have attempted to work up an example which looks logical - but cant get
around the throw that occurs at /boost/coroutine/detail/context_base.hpp:213

// linux 2.6.23, g++ (GCC) 4.1.2
// g++ -g main.cpp -lboost_coroutine-mt -lboost_system-mt

#include <iostream>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <boost/coroutine/coroutine.hpp>
#include <boost/coroutine/generator.hpp>
#include <boost/coroutine/future.hpp>
#include <boost/asio.hpp>

namespace coro = boost::coroutines;
using namespace coro;

typedef boost::asio::io_service service_type;

//typedef coro::coroutine< void()> foo_coroutine_type;
//typedef coro::coroutine< void( service_type &service)>
foo_coroutine_type;
typedef coro::shared_coroutine< void( service_type &service)>
foo_coroutine_type;

void foo( foo_coroutine_type::self &self, service_type &service)
{
    typedef boost::system::error_code error_type;
    typedef boost::asio::ip::tcp::resolver::query query_type;
    typedef boost::asio::ip::tcp::resolver::iterator iterator_type;

    boost::asio::ip::tcp::resolver resolver( service);

    query_type query( "www.boost.org", 80 );

    coro::future< error_type, iterator_type> future( self);

    resolver.async_resolve( query,
            coro::make_callback( future));

    assert( !future);
    // wait throws here --> /boost/coroutine/detail/context_base.hpp:213
    coro::wait( future);
    assert( future);

    error_type &error = future->get< 0>();

    if( error)
        std::cout << "error resolving " << error.message() << std::endl;
    else {
        iterator_type ip = future->get< 1>();
        while( ip != iterator_type())
           std::cout << ip->endpoint() << std::endl;
    }
}

int main()
{
    service_type service;

    foo_coroutine_type cfoo( boost::bind( &foo, _1, boost::ref( service)));
    cfoo();
// service.post( boost::bind( &foo_coroutine_type::operator(void ),
&cfoo));
    service.run();
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk