Boost logo

Boost Users :

Subject: [Boost-users] [ASIO] Synchronous write on serial_port
From: Daniele Barzotti (daniele.barzotti_at_[hidden])
Date: 2009-04-06 04:06:16


Hi,

I'm developing a library that use ASIO Serial Port and I need to
implement a synchronous write.

The structure is:

EuroATLib.cpp : library main file
Serial.cpp : serial port class that wrap asio::serial_port
ATDispatcher.cpp : a dispatcher object
ATModem.cpp : the consumer object

The problem is that my code writes characters on serial port very slowly
(1 char every 10 seconds) and I can't understand why.
Also, when the program ends, the io_service thread seems to be already
alive: it continues to write to serial port for a while!

The implementation is like this...can someone give me some feedback?

PS: In the following code TBUFFER is std:string.

In EuroATLib.cpp :
----------------------------------------------------------
// Main io_service
static boost::asio::io_service io_service;
static boost::scoped_ptr<boost::thread> io_service_thread;

/*!
  \brief Factory function for ATModem objects creation
*/
EXTERN_C EUROATLIB_API ATModem* CALL CreateATModemObj()
{
  static bool thread_started;
  if (!thread_started) {
    try {
      // run the IO service as a separate thread
      io_service_thread.reset(new boost::thread(
boost::bind(&boost::asio::io_service::run, &io_service) ));
      thread_started = !thread_started;
    } catch (boost::thread_resource_error e) {
      // Failed to create the new thread
      return 0;
    }
  }
  // create the new object
  return new ATModem(io_service);
};
----------------------------------------------------------

In Serial.hpp :
----------------------------------------------------------
// the main IO service that runs this connection
boost::asio::io_service& _io_service;
// the serial port this instance is connected to
boost::asio::serial_port _serialPort;
----------------------------------------------------------

In Serial.cpp :
----------------------------------------------------------

SerialPort::SerialPort(boost::asio::io_service &_io) :
                       m_buffer_size(100),
                       _io_service(_io),
                       _serialPort(_io_service),
                       _rx_timer(_io_service),
                       ReadTimeOut(READ_TIMEOUT)
{
  //init_dcs();
  EosString = '\n';
  _buf = 0;
};

BOOL SerialPort::Write(TBUFFER &buffer)
{
  _io_service.post(boost::bind(&SerialPort::do_write, this, buffer));
  return true;
};

void SerialPort::do_write(TBUFFER &buffer)
{
  // size_t byte_written = boost::asio::write(_serialPort,
boost::asio::buffer(buffer.c_str(), buffer.size()));
  size_t byte_written =
_serialPort.write_some(boost::asio::buffer(buffer.c_str(),
buffer.size()));
};

----------------------------------------------------------

In ATDispatcher.cpp simply have a SerialPort member and a function
SendCommand that start a timer and call Serial.Write(cmd)

In ATModem.cpp I have an ATDispatcher Object on which it calls
disp_obj.SendCommand("AT+CMGS"):

----------------------------------------------------------
RET_VAL ATModem::Connect(std::string DevName)
{
  if (DevName.length() > 0) SetComPort(DevName);
  if (!_serial_port.Open()) return -1;

  //Connect the OnDataReceived event to the ATDispatcher object
  _dispatcher->OnData(boost::bind(&EuroATLib::ATModem::OnDataReceived,
this));

  //Register Voice Service
  if ( _dispatcher->SendCommand("AT+CTSP=2,0,0") != ATDispatcher::RET_OK
) return DEV_AT_CMD_ERROR;
  //Register STATUS Service
  if ( _dispatcher->SendCommand("AT+CTSP=2,2,20") !=
ATDispatcher::RET_OK ) return DEV_AT_CMD_ERROR;

  this->SetStatus(STATE_READY);
};
----------------------------------------------------------

Finally in the main client program:

  // Create a ATModem object
  boost::scoped_ptr<ATModem> _devATModem( CreateATModemObj() );
  _devATModem->Connect("\\\\.\\COM1");


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