开发者

Boost asio and thread, if i run two instances i get cpu at 100%

I created a console application that sends data on a network link. I used the boost library, both the thread and the asio ones; currently i'm running it under Windows. If I run a single application it works perfectly, but if I open two instances on two different consoles, the CPU load goes to 100%, if I close one of the 开发者_如何学编程application it goes back to normal. I just used a simple socket with async reads and writes, and threads with condition variables and mutexes. Is there any special thingh to do when dealing with such a situation? I can show you some code, but I think it's nothing special:

socket->connect(tcp::endpoint(address::from_string(getAddress()),getPort()));

for connecting

and

socket->async_read_some(buffer(receiveData),bind(&NetworkLink::handle_response, this,placeholders::error,placeholders::bytes_transferred));

inside the handle_response function for async reading. For the thread I use

boost::unique_lock<boost::mutex> messages_lock(message_received_mutex);

Before deleting everything and starting a simple test project from scratch I would like to know if there are any special care to be taken in this situation.


Ok it seems I've tracked down the problem. First of all, the 100% CPU usage was due to the fact that each instance was using 50% of the CPU (I'm on a dual core PC). So I run all over the code and found out this. I had this in my code, inside the NetworkLink::handle_response function:

socket->async_read_some(
    boost::asio::buffer(receiveData),
    boost::bind(&NetworkLink::handle_response, this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred));
io_service.run();

I used the io_service.run(); because before the software was not receiving data. Now I removed the line, I don't get the 50% CPU usage, but the handler response is not called so I cannot receive any data. Any thought about this? Thanks

PS: I created a small app that shows this problem:

#include <iostream>
#include <boost/asio.hpp>
#include "boost/thread.hpp"
#include "boost/thread/mutex.hpp"

#ifdef _WIN32
#include "Windows.h"
#endif

using namespace boost::asio::ip;
using namespace std;

std::vector<uint8_t> buf;
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket mysocket(io_service);

int handle_response(const boost::system::error_code &err,
        size_t bytes_transferred)
{
    // cout << bytes_transferred << ' ';
    if (bytes_transferred > 0)
        cout << buf.data() << ' ';
    boost::asio::async_read(mysocket, boost::asio::buffer(buf),
            boost::asio::transfer_at_least(1), &handle_response);
}

int mythread()
{
    boost::asio::async_read(mysocket, boost::asio::buffer(buf),
            boost::asio::transfer_at_least(1), &handle_response);

    io_service.run();
}

int main()
{
    int m_nPort = 12345;

    buf.resize(100, '0');
    boost::condition_variable message_received_condition;
    boost::thread message_receiver_thread(&mythread);
    boost::mutex messages_mutex;

    tcp::endpoint endpoint(boost::asio::ip::address::from_string("127.0.0.1"),
            m_nPort);

    boost::unique_lock<boost::mutex> messages_lock(messages_mutex);
    message_received_condition.notify_one();

    cout << "Waiting for connection..." << endl;

    Sleep(10000);
    mysocket.connect(endpoint);
    cout << "connection accepted" << endl;
    try
    {
        while (true)
        {
            boost::system::error_code ec;
            boost::asio::socket_base::bytes_readable command(true);
            mysocket.io_control(command);
            std::size_t bytes_readable = command.get();

            mysocket.async_read_some(boost::asio::buffer(buf),
                    &handle_response);

            io_service.run();
        }
    } catch (exception &e)
    {
        cerr << e.what() << endl; //"The parameter is incorrect" exception
    }
}

If you remove the comment from th line // cout << bytes_transferred << ' '; in the handle response functionyou get a lower CPU usage, I guess because of the delay for writing to the screen.


You are not checking the error. If there is a failure, you continue to read anyway, which will probably immediately post back a completion with a failure, ad infinitum.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜