I am a bit lost in a construct of libraries, which I have to tangle together. I need help to indtroduce some timers into this construct.
I have the following:
- com.cpp which has
main
and includes com.hpp
- com.hpp which includes a host.h and needed boost includes and defines a class comClient
- host.c with included host.h
- wrapper.cpp with included com.hpp and some needed boost includes
Now, my com.cpp is creating a comClient and uses it for asynch communication on the com-port. Using boost::asio::serial_port
and boost::asio::io_service
.
I need to work with some timers, in order to catch when a paket needed too long to transmit.
When creating an instance of comClient, the paket-timer should be initialised.
Using asynch_read_some
in a private function of comClient, I call a private handler of comClient, then this handler calls a function of host.c, which calls to the wrapper.cpp a function to restart the timer.
This is the function to init the timer:
//wrapper.cpp
void IniPacketTimer(void *pCHandle){
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::milliseconds(25));
t.async_wait(&hostOnTimeout(pCHandle));
io.run();
}
This would be the command chain in short:
//comClient.cpp
main{
comClient cc();
}
//comClient.hpp
class comClient(boost::asio::io_service& io_service){
comClient(){
hostInit();
aread();
}
private:
aread( call aread_done)
areaddone(call hostNewData())
}
//host.c
hostInit(){
IniPacketTimer()
}
hostNewData(){
resetTimer
}
//wrapper.cpp
resetTimer(){
t.expires_from_now
}
Questions:
How can I provide an asynchronous timer, which does not affect the asynch read/write operations on my serial port, but triggers execution of a function when the deadline is hit?
Should I use the already existing io_service
or is it ok, if I just create another?
Why do I get an error C2102 '&' expects L-Value for my line t.async_wait
?
You problem is not clear and since you don't post real code it is quite hard to guess what your problem is.
Especially your threading is not clear but for asio very important.
Below is an example that will compile but not run. I hope it gives you an hint on how to proceed.
It will open a serial port and a timer. Whenever the timer expires it will start a new one. It is a stripped version of code I used some time ago so maybe it will help you.
#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <vector>
class SerialCommunication
{
public:
SerialCommunication(boost::asio::io_service& io_service, const std::string& serialPort)
: m_io_service(io_service)
, m_serialPort(m_io_service)
, m_timeoutTimer(m_io_service, boost::posix_time::milliseconds(5))
{
configureSerialPort(serialPort);
}
void configureSerialPort(const std::string& serialPort)
{
if(m_serialPort.is_open())
{
m_serialPort.close();
m_timeoutTimer.cancel();
}
boost::system::error_code ec;
m_serialPort.open(serialPort, ec);
if(m_serialPort.is_open())
{
// start Timer
m_timeoutTimer.async_wait(boost::bind(&SerialCommunication::TimerExpired, this, _1));
header_sync();
}
}
void header_sync()
{
m_serialPort.async_read_some(boost::asio::buffer(&m_header.back(), 1),
boost::bind(&SerialCommunication::header_sync_complete, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void header_sync_complete(
const boost::system::error_code& error, size_t bytes_transferred)
{
// stripped
read_payload(&m_payload[0], 0);
}
void read_payload(uint8_t* buffer, uint8_t length)
{
m_serialPort.async_read_some(boost::asio::buffer(buffer, length),
boost::bind(&SerialCommunication::payload_read_complete, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void payload_read_complete(
const boost::system::error_code& error, size_t bytes_transferred)
{
// stripped
// timer cancel and reset
m_timeoutTimer.cancel();
m_timeoutTimer.expires_at(boost::posix_time::microsec_clock::local_time() +
boost::posix_time::milliseconds(5));
m_timeoutTimer.async_wait(boost::bind(&SerialCommunication::TimerExpired, this, _1));
memset(&m_header[0], 0, 3);
header_sync();
}
void TimerExpired(const boost::system::error_code& e)
{
m_timeoutTimer.expires_at(m_timeoutTimer.expires_at() + boost::posix_time::milliseconds(5));
m_timeoutTimer.async_wait(boost::bind(&SerialCommunication::TimerExpired, this, _1));
}
boost::asio::io_service& m_io_service;
boost::asio::deadline_timer m_timeoutTimer;
boost::asio::serial_port m_serialPort;
std::vector<uint8_t> m_header;
std::vector<uint8_t> m_payload;
};
int main()
{
boost::asio::io_service io_service;
SerialCommunication cc(io_service, "/dev/ttyS0");
io_service.run();
return 0;
}