Skip to content

Commit b15daec

Browse files
committed
Implement timeout for async data read
1 parent fffa209 commit b15daec

File tree

3 files changed

+80
-10
lines changed

3 files changed

+80
-10
lines changed

qt/reader.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <QTextBlock>
1111
#include <QTextCursor>
1212

13-
#define READ_TIMEOUT 10000
13+
#define READ_TIMEOUT 10
1414
#define NOTIFY_LIMIT 131072 // 128KB
1515

1616
Q_DECLARE_METATYPE(QtMsgType)
@@ -257,20 +257,13 @@ int Reader::read(char *pbuf, uint32_t len)
257257
std::function<void(int)> cb = std::bind(&Reader::readCb, this,
258258
std::placeholders::_1);
259259

260-
if (serialPort->asyncRead(pbuf, len, cb) < 0)
260+
if (serialPort->asyncReadWithTimeout(pbuf, len, cb, READ_TIMEOUT) < 0)
261261
{
262262
logErr("Failed to read data");
263263
return -1;
264264
}
265265

266266
return 0;
267-
268-
//TODO: handle timeout
269-
// if (!serialPort->waitForReadyRead(READ_TIMEOUT))
270-
// {
271-
// logErr("Read data timeout");
272-
// return -1;
273-
// }
274267
}
275268

276269
int Reader::serialPortCreate()

qt/serial_port.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,65 @@ void SerialPort::onRead(const boost::system::error_code &ec, size_t bytesRead)
7878
readCb(bytesRead);
7979
}
8080

81+
int SerialPort::asyncReadWithTimeout(char *buf, int size,
82+
std::function<void (int)> cb, int timeout)
83+
{
84+
if (!port || !port.get() || !port->is_open())
85+
return -1;
86+
87+
readCb = cb;
88+
89+
port->async_read_some(boost::asio::buffer(buf, size),
90+
boost::bind(&SerialPort::onReadWithTimeout, this,
91+
boost::asio::placeholders::error,
92+
boost::asio::placeholders::bytes_transferred));
93+
94+
timer = timer_ptr(new boost::asio::deadline_timer(ioService));
95+
timer->expires_from_now(boost::posix_time::seconds(timeout));
96+
timer->async_wait(boost::bind(&SerialPort::onTimeout, this,
97+
boost::asio::placeholders::error));
98+
99+
if (!isStarted)
100+
{
101+
thread = thread_ptr(new boost::thread(boost::bind(&boost::asio::
102+
io_service::run, &ioService)));
103+
isStarted = true;
104+
}
105+
106+
return 0;
107+
}
108+
109+
void SerialPort::onReadWithTimeout(const boost::system::error_code &ec,
110+
size_t bytesRead)
111+
{
112+
boost::mutex::scoped_lock look(mutex);
113+
114+
timer->cancel();
115+
timer = nullptr;
116+
117+
if (ec)
118+
{
119+
readCb(-1);
120+
isStarted = false;
121+
return;
122+
}
123+
124+
readCb(bytesRead);
125+
}
126+
127+
void SerialPort::onTimeout(const boost::system::error_code &e)
128+
{
129+
if (!e)
130+
{
131+
std::cout << "timeout: " << e.message() << std::endl;
132+
port->cancel();
133+
readCb(-1);
134+
isStarted = false;
135+
}
136+
else if (e != boost::asio::error::operation_aborted)
137+
std::cout << "Timer error: " << e.message() << std::endl;
138+
}
139+
81140
std::string SerialPort::errorString()
82141
{
83142
return ec.message();
@@ -119,6 +178,12 @@ void SerialPort::stop()
119178
{
120179
boost::mutex::scoped_lock look(mutex);
121180

181+
if (timer)
182+
{
183+
timer->cancel();
184+
timer = nullptr;
185+
}
186+
122187
if (port)
123188
{
124189
port->cancel();
@@ -130,4 +195,7 @@ void SerialPort::stop()
130195
ioService.stop();
131196
ioService.reset();
132197
isStarted = false;
198+
199+
if (thread)
200+
thread = nullptr;
133201
}

qt/serial_port.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,29 @@
1414

1515
#include <iostream>
1616

17-
typedef boost::shared_ptr<boost::asio::serial_port> serial_port_ptr;
17+
typedef boost::shared_ptr<boost::thread> thread_ptr;
18+
typedef boost::shared_ptr<boost::asio::serial_port> serial_port_ptr;
19+
typedef boost::shared_ptr<boost::asio::deadline_timer> timer_ptr;
1820

1921
class SerialPort
2022
{
2123
private:
2224
boost::asio::io_service ioService;
25+
thread_ptr thread;
2326
serial_port_ptr port;
2427
boost::system::error_code ec;
2528
boost::mutex mutex;
29+
timer_ptr timer;
2630
std::function<void(int)> readCb;
2731
bool isStarted = false;
2832

2933
SerialPort(const SerialPort &p);
3034
SerialPort &operator=(const SerialPort &p);
3135

3236
void onRead(const boost::system::error_code &ec, size_t bytesRead);
37+
void onReadWithTimeout(const boost::system::error_code &ec,
38+
size_t bytesRead);
39+
void onTimeout(const boost::system::error_code &e);
3340

3441
public:
3542
SerialPort();
@@ -41,6 +48,8 @@ class SerialPort
4148
int write(const char *buf, int size);
4249
int read(char *buf, int size);
4350
int asyncRead(char *buf, int size, std::function<void(int)> cb);
51+
int asyncReadWithTimeout(char *buf, int size, std::function<void (int)> cb,
52+
int timeout);
4453
std::string errorString();
4554
};
4655

0 commit comments

Comments
 (0)