Boost::Asio synchronous I/O operation with timeout

Discussion in 'C++' started by Antonio Di Monaco, Apr 14, 2012.

  1. Hi,

    I don't know if I'm [OT] about my question here, but I didn't find any
    Boost-related groups.

    I have a question about Boost Asio, better say a need of clarification.
    Let me summarize my problem
    first. I need to control a TCP device, that works like that:

    a) it always wait for a command, and returns a response
    b) both command and response lengths are known in advance, so I know how
    many bytes I expect in both directions
    c) sequence command/response is atomic, i.e. it doesn't accept another
    command before having replied to the first one

    So I implemented synchronous read/write operations using Boost Asio. I
    clarify that my solution works perfectly, I just need
    to know if it was implemented in the way it should be, cause it was a
    result of "try-and-pray", and maybe my result isn't the
    proper way to manage this problem.

    For the sake of brevity, I'm posting only write method, cause read one
    has the same layout:

    int IONetworkSocket::doWrite(const std::vector< unsigned char > &vData)
    {
    boost::system::error_code timerResult;
    boost::system::error_code writeResult;
    std::size_t bytesWritten = 0;

    bool timeout = false, ioError = false, ignoreTimeout = false,
    ignoreIoError = false;
    unsigned int transaction = _currentTransaction;

    boost::asio::deadline_timer timer(ioService());

    timer.expires_from_now(boost::posix_time::milliseconds(writeTimeOut()));
    timer.async_wait([&timerResult, &timeout, &ignoreIoError, transaction,
    this] (const boost::system::error_code &cError)
    {
    boost::lock_guard< boost::mutex >
    guard(this->_transactionMutex);

    if (transaction == this->_currentTransaction)
    {
    ++(this->_currentTransaction);
    timeout = true;
    timerResult = cError;
    ignoreIoError = true;
    }
    });

    boost::asio::async_write(socket(),boost::asio::buffer(vData,vData.size()),boost::asio::transfer_all(),
    [&writeResult, &ioError, &bytesWritten,
    &ignoreTimeout, &timer, transaction, this]
    (const boost::system::error_code &cError,
    std::size_t iBytesTransferred)
    {
    boost::lock_guard< boost::mutex >
    guard(this->_transactionMutex);

    if (transaction == this->_currentTransaction)
    {
    ++(this->_currentTransaction);
    writeResult = cError;
    bytesWritten = iBytesTransferred;
    ioError = cError.value() != 0;
    ignoreTimeout = true;
    timer.cancel();
    }
    });

    ioService().reset();

    boost::system::error_code ioEc;
    while (ioService().run_one(ioEc))
    if (ioError && !ignoreIoError)
    {
    ... something went wrong during I/O, return with error code ...
    }
    else if (timeout && !ignoreTimeout)
    {
    ... timeout occurred, return with timeout error code ...
    }

    ... here everything should be fine ...
    }


    The usage of "while (ioService().run_one(ioEc))" was the result of
    googling around, and that's my doubt.

    What I was trying to implement is:

    a) block my thread, waiting for only ONE of the two handlers to complete
    b) when one of the two handlers completes, I'd like to destroy the other
    handler, i.e. I don't mind if it completes or not,
    but I don't want to be notified of it

    My first version called ioService().run_one(ioEc) without any while
    loop, and had no mutex-protected _currentTransaction member.
    What happened is that, even if I call ioService().reset(), when
    performing read after write, all past handlers are processed,
    accessing to references of variables that no longer exist.

    I solved my problem using a transaction number, that is "frozen" in both
    handlers at invocation, due to pass-by-value during
    capture. When one of the handlers get called, increments the transaction
    number, so if in future past handlers are called, they
    go out quickly without any damages.

    Are there any better solutions? This is my first attempt with Boost
    Asio, probably I misunderstood some of its basic principles :(

    Thanks a lot,
    Antonio.
     
    Antonio Di Monaco, Apr 14, 2012
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?utf-8?B?5byg5rKI6bmP?=

    How to compile the HelloWorld of boost.asio?

    =?utf-8?B?5byg5rKI6bmP?=, Aug 10, 2006, in forum: C++
    Replies:
    1
    Views:
    3,525
    Victor Bazarov
    Aug 10, 2006
  2. Replies:
    1
    Views:
    1,227
    Martin York
    Apr 20, 2008
  3. Torsten Mueller

    boost::asio for HTTP -> data truncated

    Torsten Mueller, Aug 12, 2010, in forum: C++
    Replies:
    3
    Views:
    2,041
    Francesco S. Carta
    Aug 13, 2010
  4. Christopher
    Replies:
    0
    Views:
    1,410
    Christopher
    Jun 8, 2011
  5. Torsten Mueller
    Replies:
    1
    Views:
    465
    Bart van Ingen Schenau
    Jun 23, 2013
Loading...

Share This Page