Не работает ли boost :: asio :: strand в Ubuntu 11.04 (boost_all_dev 1.42) - PullRequest
1 голос
/ 18 мая 2011

У меня есть программа, которая использует io_service и несколько потоков.

Она создает некоторое количество объектов сокетов.Каждый из этих объектов имеет цепь для синхронизации.Все вызовы async_read (), async_write () и подобных функций проходят через strand_.wrap (boost :: bind (...)).Каждый объект также имеет переменную int interlock_, которая инициализируется равной 0.

Внутри одной из этих функций (обратный вызов при получении данных) я делаю следующее:

Class::startRead(...)
{
...
    boost::asio::async_read(socket_, boost::asio::buffer(ptr, 16384), boost::asio::transfer_at_least(1),
        strand_.wrap(boost::bind(&EagerConnection::on_read, this, placeholders::error, placeholders::bytes_transferred)));
}

Class::on_read(...)
{
...
    startRead();
    assert(0 == __sync_fetch_and_add(&interlock_, 1));
    onData_();
    assert(1 == __sync_fetch_and_add(&interlock_, -1));
}

, посколькувсе синхронизируется через нить, что первое утверждение никогда не должно срабатывать.Тем не менее, это действительно огонь!Когда я проверяю значение в GDB, конечное значение interlock_ равно 2, что означает, что два отдельных вызова on_read () активны одновременно.

Означает ли это, что boost :: asio :: strandсломано?(Я уже проверил, что у меня нет повторного входа в функцию завершения - обработчик сигнала onData_ не вызывает повторно on_data ()).

Может ли "ранний" startRead как-то вызватьнемедленный повторный въезд?(Кажется, что и семантика async_x, и strand указывают на то, что это невозможно)

Если вы действительно, действительно хотите увидеть полный контекст класса, он доступен в виде сущности: https://gist.github.com/979212

Ответы [ 2 ]

0 голосов
/ 19 мая 2011

Я заметил несколько незначительных (?) Проблем:

  • Незначительный: порядок инициализации interlock_ и strand_ переключен.Исправьте это, объявив interlock_ _after_ член strand_;

  • Функция readIn не возвращает значения (неинициализированные данные).Вы, вероятно, намереваетесь вернуть n?


Хорошие новости:

  • Бег с valgrind включился ясно.с включенным helgrind (но: я не использую нити в моем минимальном примере, я думаю; не знаю о boost::asio и boost::signals внутренностях).
0 голосов
/ 19 мая 2011

Я пытаюсь воспроизвести что-то, но моя установка не может выдать подтверждения при этом.

Я добавил следующий фрагмент в конце сущности:

int split(std::string const &src, char ch, std::string &oLeft, std::string &oRight)
{
    std::size_t pos = src.find(ch);
    if (pos == std::string::npos)
    {
        oLeft = src;
        oRight.clear();
        return 1;
    } else
    {
        oLeft = src.substr(0, pos);
        oRight = src.substr(pos+1);
        return 2;
    }
}

namespace {

    boost::asio::io_service svc;
    EagerConnection c(svc);

    void onconnect()
    {
        std::cout << "ONCONNECT" << std::endl;
        const char data[] = "GET / HTTP/1.0\r\n\r\n"; 
        c.writeOut(data, sizeof(data));
    }

    void ondata()
    {
        std::cout << "ONDATA" << std::endl;
        std::ostringstream oss;
        char buf[1024];
        int read;
        while ((read = c.readIn(buf, 1024)))
            oss.write(buf, read);
        std::cout << "response: " << oss.str() << std::endl;
    }

    void ondisconnect()
    {
        std::cout << "ON__DIS__CONNECT" << std::endl;
    }

}

int main(int argc, char* argv[])
{
    if (argc>1 && argv[1])
    {
        c.onConnect_.connect(&onconnect);
        c.onData_.connect(&ondata);
        c.onDisconnect_.connect(&ondisconnect);


        c.open(argv[1]);
        svc.run();
    }

    return 0;
}

Как вы можете видеть, я действительно пытаюсь выполнить простейшую задачу, которую можно выполнить. Мое соединение / переподключение работает хорошо (в том числе увеличение времени отката).

Я компилирую это с

strand: strand.cpp
    g++ -Wall -Werror -o $@ $^ -g -O0 -lboost_system -lboost_thread -lboost_signals -lpthread

И вызвать его с помощью

./strand 127.0.0.1:6767

У меня есть сценарий-ответчик, который делает (в основном)

netcat -l -p 6767 -e rev

Еще одна вещь, на которую следует обратить внимание: кажется, что буфер записи никогда не отправляется / сбрасывается до тех пор, пока я не прерву тестер strand (на стороне клиента). Это происходит независимо от того, насколько большой я делаю data ... Это, вероятно, из-за пропущенного шага?

Редактировать :

Проверено идентично на

  • Ubuntu Meerkat, GCC 4.4,5, Boost 1,42,0
  • debian sid, gcc 4.5.2-8, boost 1.46.1
...