0
votes

I have a server and a client code written in boost ASIO and it works pretty fine. Since synchronous and asynchornous boost asio API's are different, is it possible in any way that the code I have written for asynchronous communication behaves and works in a synchronous fashion instead of asynchronous. ?

1
What do you mean? What code do you have, and exactly what parts do you want to run synchronously. What does it mean for it to run synchronously? - sehe
So, @sehe , what I mean is that I have a code written using async_accept, async_read and async_write. What asynchronous API's do is that when the I/O operation is complete, they call a function which does post processing. Whereas, with synchronous I/O, unless the current i/o is complete, it cannnot go to the next operation. So, what I was asking i that can the code written using async API's be used to do synchronous i/o ? - Nishant Sharma
My answer shows it - sehe
@NishantSharma Please remember to accept an answer to your question[s]. - Blacktempel

1 Answers

2
votes

You can run any asynchronous code on a dedicated io_service, and simply run the service blocking:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <iostream>

using namespace std::chrono_literals;
using namespace boost::asio;
using boost::system::system_error;

io_service svc;
high_resolution_timer deadline(svc, 3s);

void task_foo() { 
    deadline.async_wait([](system_error) { std::cout << "task done\n"; });
}

int main() {
    task_foo();

    std::cout << "Before doing work\n";

    svc.run(); // blocks!

    std::cout << "After doing work\n";
}

Prints

Before doing work
task done
After doing work

Alternatively:

You can always use futures that you can then await blocking:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <boost/make_shared.hpp>
#include <future>
#include <iostream>
#include <thread>

using namespace std::chrono_literals;
using namespace boost::asio;
using boost::system::system_error;

io_service svc;
high_resolution_timer deadline(svc, 3s);

std::future<int> task_foo() {
    auto p   = boost::make_shared<std::promise<int> >();
    auto fut = p->get_future();

    deadline.async_wait([p](system_error) {
        std::cout << "task done\n";
        p->set_value(42);
    });

    return fut;
}

int main() {

    auto foo = task_foo();

    std::cout << "Before doing work\n";

    std::thread([] { svc.run(); }).detach(); // doesn't block!

    std::cout << "After starting work\n"; // happens before task completion

    auto result = foo.get(); // blocks again!

    std::cout << "Task result: " << result << "\n";
}

Prints

Before doing work
After starting work
task done
Task result: 42

This way you can still have the io_service running concurrently and don't require it to complete even though a particular task completes synchronously (foo.get())