Boost logo

Boost Users :

Subject: Re: [Boost-users] [asio] serial_port question
From: Michael Caisse (boost_at_[hidden])
Date: 2009-08-25 21:49:45


Robert Dailey wrote:
> On Tue, Aug 25, 2009 at 6:36 PM, Michael Caisse
> <boost_at_[hidden]
> <mailto:boost_at_[hidden]>> wrote:
>
>
>
> Why are you having to poll?
>
>
> What I'm really asking is: How do you know when to call
> async_read_some()? Ideally I only want to call into the socket to read
> information when I get a callback saying that there is actually
> something in the read buffer to get. A short sequence of what I want
> to happen:
>
> 1. Send a message over the COM port
> 2. Wait for the device to reply (The device would send a message back)
> 3. Receive a callback saying that a new message (new data) is
> available and ready to be read
> 4. Call async_read() to obtain that data.
>

Robert -

It looks like you might be thinking about the problem in a synchronous
manner.

Let me suggest a different way to think about the problem. Let us pretend
that your messages across the COM port are delimited in some manner (like
a standard STX/ETX). You now have some object that invokes an async_read_some
for the port and just waits. I wont digress on all the reasons I think
async_read_some is the right choice... for now lets just assume that my way
works (o;

The completion handler for async_read_some will look for the STX and then
collect bytes until it finds an ETX. When the completion handler is called
it may very well not have an entire message in the buffer. That is fine.
It will just start another async_read_some. Eventually a message will be
formed. This is a good point to receive your callback saying that a new message
is available. Not only available... but here it is.

That is the basic idea. When do you call async_read? Right after you open the
port. The reads are just going on in the background putting together useful atoms
of data and then alerting you that something worthwhile is available to look at.

So... you might have some thing like this: (I'm just now making this up for illustration
... not for efficiency and may not even work)

void my_message_maker::read_start()
{
   serial_port.async_read_some( boost::asio::buffer( in_message, MAX_MESSAGE_SIZE ),
                                boost::bind( &my_message_maker::read_done,
                                             this,
                                             boost::asio::placeholders::error,
                                             boost::asio::placeholders::bytes_transferred ) );
}

void my_message_maker::read_done( const boost::system::error_code& error,
                                  int bytes_transferred )
{
   if( !error )
   {
      for( int i=0; i < bytes_transferred; ++i )
      {
         if( in_message[ i ] == STX )
         {
            my_message.clear();
         }
         else if( in_message[ i ] == ETX )
         {
            make_callback( my_message );
         }
         else
         {
            my_message += in_message[ i ];
         }
      }
   }
   else
   {
      close_port( error );
   }
}

I hope this helps some. Obviously the example has issues but it might give you
another way to think about the problem.

Michael

-- 
----------------------------------
Michael Caisse
Object Modeling Designs
www.objectmodelingdesigns.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net