Szymon Madera
Szymon Madera

Reputation: 97

How to run io_service in other thread?

I am trying to run udp server. The problem is blocking run() call on io_service. So i decided to run this method on other thread using boost bind. In result the main thread execution goes out of DictionaryImpl constructor scope, but when i send udp package, tcpdump tells me that my port is unreachable. When i call run() call on io_service in the main thread everything is ok. Where is problem?

class DictionaryImpl  {
    boost::asio::io_service io;
    boost::scoped_ptr<boost::thread> thread;

public:
    DictionaryImpl() {
        try {
            udp_server2 udpReceiver(io);

            thread.reset(new boost::thread(
                    boost::bind(&DictionaryImpl::g, this, std::ref(io))));

        } catch (std::exception &e) {
            std::cerr << "Exception: " << e.what() << "\n";
        }

    }

    void g(boost::asio::io_service & io){
        io.run();
    }

    virtual ~DictionaryImpl() {
        if (!thread) return; // stopped
        io.stop();
        thread->join();
        io.reset();
        thread.reset();
    }

};






class udp_server2
{
public:
    udp_server2(boost::asio::io_service& io_service)
            : socket_(io_service, udp::endpoint(udp::v4(), 13003))
    {
        start_receive();
    }

private:
    void start_receive()
    {
        socket_.async_receive_from(
                boost::asio::buffer(recv_buffer_), remote_endpoint_,
                boost::bind(&udp_server2::handle_receive, this,
                            boost::asio::placeholders::error,
                            boost::asio::placeholders::bytes_transferred));
    }

    void handle_receive(const boost::system::error_code& error,
                        std::size_t /*bytes_transferred*/)
    {
        if (!error || error == boost::asio::error::message_size)
        {
            std::cout<<"handle_receive\n";    
            start_receive();
        }
    }



    udp::socket socket_;
    udp::endpoint remote_endpoint_;
    boost::array<char, 1> recv_buffer_;
};

Upvotes: 0

Views: 668

Answers (1)

Richard Hodges
Richard Hodges

Reputation: 69892

DictionaryImpl's io_service will stop when it runs out of work. You can prevent this with the use of asio::io_service::work.

In ~DictionaryImpl you are calling reset after calling stop on the io_service. The only time you'd want to do this is if you plan to subsequently restart the io_service.

It looks like you would benefit from revisiting the documentation (which I accept is a little sparse). Have a look at the multi-threaded examples in the asio docs also. They will show examples of using a work object.

Upvotes: 1

Related Questions