Ælex
Ælex

Reputation: 14869

boost io_service non-blocking parallel execution?

I have run into a dilemma whilst using boost::asio and boost::io_service

My classes wrap around the async client example provided by boost for socket connections. I use another class which encapsulates:

class service_controller
{
    ...

    /// IO service
    boost::asio::io_service __io_service;

    /// Endpoint Resolver
    boost::asio::ip::tcp::resolver::query __query;

    /// Resolution for TCP
    boost::asio::ip::tcp::resolver __resolver;
}

So, when I construct my clients, the constructor takes references:

asio_service_client (
                        boost::asio::ip::tcp::resolver::query & query,
                        boost::asio::ip::tcp::resolver & resolver,
                        boost::asio::io_service & io_service
                    );

Everything works fine, but I have to call

io_service.run()

At the end, after creating all all my clients. If I encapsulate seperate io_service objects for each client, I essentially remove the async io nature, as each one will block until its finished. Therefore, I decided to form a type of group, by making all client objects use the same io_service.

io_service::poll() does not appear to work at all (nothing happens), nor does io_service::run_one().

In fact, the only thing that appears to work, is:

    // with a callback => the callback will run once finished
    rapp::services::asio_service_client c1( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );

    // without a callback => asio_service_client::handle_reply will run once finished
    rapp::services::asio_service_client c2 ( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );
    rapp::services::asio_service_client c3 ( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );
    rapp::services::asio_service_client c4 ( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );

    // Run services c1, c2
    c1.Run( header, post,
            [&]( boost::asio::streambuf & buffer )
            { 
                std::string raw ( ( std::istreambuf_iterator<char>( &buffer ) ), std::istreambuf_iterator<char>() );
                std::cout << raw << std::endl;
            });

    c2.Run( header, post );
    ctrl.Services().run();

    /// Run remaining services ( c3, c4 )
    c3.Run( header, post );
    c4.Run( header, post );

    ctrl.Services().reset();
    ctrl.Services().run();

Unless of course, if I request a group to be run altogether (e.g., ask for c1, c2, c3 and c4 Run).

Is there some way, or some class pattern, where I could automate a queue, where I create objects, add them, and they are run asynchronously? Ideally with threads, but without will also work.

Some kind of a stack, where whilst I add objects, they are asynchronously executed, as they are added.

If I try something like:

Scheduler::Execute ( asio_service_client & client )
{
   client.Run( ... )
   io_service.reset();
   io_service.run();
}

I will reset previous running services, and start all over, which is not what I want. My only obvious option, is to either accept and assign a separate io_service for each added asio_service_client, or force them to be added all together in a job group, which is then executed?

The other solution I can think of, is using threads, thereby, each asio_service_client will run in its own thread, and thus won't block other asio_service_clients, executing in parallel?

Upvotes: 1

Views: 1403

Answers (1)

sehe
sehe

Reputation: 393537

You probably want to share a single io_service instance and post a io_service::work object on it so it stays active even if no client currently has any pending asycn operations:

boost::asio::io_service io_service;
auto work = boost::make_shared<boost::asio::io_service::work>(io_service);

// any client can post it's asynchronous operations on this service object, from any thread

// completion handlers will be invoked on any thread that runs `io_service.run()`

// once you want the `io_service` to empty the queue and return:
work.reset();

// now `run()` will return when it runs out of queued tasks

Upvotes: 2

Related Questions