mardi 26 juillet 2016

Why does my asynchronous operations not launch?

I recently met a problem with boost::asio asynchronous tasks. I want to return a pointer on an object listening to a port. It works when I use the socket.read_some method but this method blocks my main and I want my MyClass::create method to return.

So I tried a async_read call but I saw that inside my read() method, no asynchronous tasks are launched. I tried to figure out what may cause the problem but see no solution to this issue.

Here is my code, here it's not with an async_read but with an async_wait, and the same problem appears, the timer is not launched.

Thanks for any help I might get.

The header file:

#ifndef MYCLASS_HPP
#define MYCLASS_HPP

#include <memory>
#include <boost/asio.hpp>

class MyClass
{
public:
MyClass(boost::asio::io_service& ios);

void read();
void read_handler(const boost::system::error_code& error);

static std::shared_ptr<MyClass> create(std:: string const & host, uint16_t port);

bool connect (std::string const & host, uint16_t port);
void connect_handler(const boost::system::error_code& error);


boost::asio::ip::tcp::socket    m_socket;
bool                m_flag;
std::vector<uint8_t>        m_buffer;   
};

#endif

Source file:

#include "MyClass.hpp"

#include <boost/bind.hpp>

MyClass::MyClass(boost::asio::io_service& ios)
    :m_flag(false), m_socket(ios), m_buffer(20)
{   
}

void MyClass::read_handler(const boost::system::error_code& er)
{
    std::cout << "Timer waited 5 sec" << std::endl;
}


void MyClass::read()
{
    boost::asio::deadline_timer t(m_socket.get_io_service(),boost::posix_time::seconds(5));
    t.async_wait(boost::bind(&MyClass::read_handler,this,boost::asio::placeholders::error));
    m_socket.get_io_service().run();//Should make the io_service wait for all asynchronous tasks to finish
    std::cout << "This message should be displayed after the wait" << std::endl;
}

void MyClass::connect_handler(const boost::system::error_code& error)
{
    if(!error)
    {
        std::cout << "Connection done" << std::endl;
        m_flag = 1; 
    }
    else 
    {
        std::cout << "Error in connection: " << error.message() << std::endl;
    }
}


//connect method
bool MyClass::connect(std::string const & host, uint16_t port)
{
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(host),port);

    m_socket.async_connect(endpoint, 
            boost::bind(&MyClass::connect_handler, this,
            boost::asio::placeholders::error));

    m_socket.get_io_service().run();//Wait async_connect and connect_handler to finish

    if (m_flag == 0) return false;
    else return true;
}


std::shared_ptr<MyClass> MyClass::create(std:: string const & host, uint16_t port)
{
    boost::asio::io_service ios;

    std::shared_ptr<MyClass> ptr(new MyClass(ios));

    bool bol = ptr->connect(host, port);
    ptr->read();

    //while(1){}

    if(bol == true)
    {
        //connection success, reading currently listening, pointer is returned to the user
        return ptr;
    }
    else
    {
        //connection failure, pointer is still returned to the user but not listening as he's not connected
        return ptr;
    }
}

And my main:

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
#include "MyClass.hpp"

int main()
{
    try
    {
    std::cout << "Creation of instance" << std::endl;

    std::shared_ptr <MyClass> var = MyClass::create("127.0.0.1", 8301);

    std::cout << "Instance created" << std::endl;



    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

Aucun commentaire:

Enregistrer un commentaire