为什么 QSerialPort::writeData 使用单次定时器开始写入?
Why does QSerialPort::writeData start writes with a single-shot timer?
我正在尝试了解 Qt 的串口模块,但我不太熟悉 Qt 如何处理异步 I/O。在 Windows 上,QSerialPort::writeData
方法将要写入的数据放入环形缓冲区,然后在其 timeout
信号触发时启动单次 QTimer
以实际执行写入:
qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
{
Q_Q(QSerialPort);
writeBuffer.append(data, maxSize);
if (!writeBuffer.isEmpty() && !writeStarted) {
if (!startAsyncWriteTimer) {
startAsyncWriteTimer = new QTimer(q);
QObjectPrivate::connect(startAsyncWriteTimer, &QTimer::timeout, this, &QSerialPortPrivate::_q_startAsyncWrite);
startAsyncWriteTimer->setSingleShot(true);
}
if (!startAsyncWriteTimer->isActive())
startAsyncWriteTimer->start();
}
return maxSize;
}
readData
方法不使用定时器,而是直接调用ReadFileEx
。
与仅调用 WriteFileEx
相比,单次计时器完成了什么?
间隔为 0 的 QTimer
有一个特殊情况:一旦控制 returns 到 event loop. The implementation on Unix/Linux does something similar,该计时器将触发,但不使用 QTimer,而是使用QSocketNotifier
的子类,当可以写入端口时将被调用。这两种实现都意味着您将缓冲数据并在返回主事件循环后将其写出。
我认为这样做有两个原因:
- POSIX 和 Win32 串行 API 之间存在一些不同之处,需要以这种方式构建代码。据我所知,情况并非如此
- @Mike 在评论中所说:这将允许在写入数据之前对其进行缓冲
缓冲似乎是最可能的原因,因为对您要写入的每条数据执行系统调用将是一项相当昂贵的操作。
我正在尝试了解 Qt 的串口模块,但我不太熟悉 Qt 如何处理异步 I/O。在 Windows 上,QSerialPort::writeData
方法将要写入的数据放入环形缓冲区,然后在其 timeout
信号触发时启动单次 QTimer
以实际执行写入:
qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize)
{
Q_Q(QSerialPort);
writeBuffer.append(data, maxSize);
if (!writeBuffer.isEmpty() && !writeStarted) {
if (!startAsyncWriteTimer) {
startAsyncWriteTimer = new QTimer(q);
QObjectPrivate::connect(startAsyncWriteTimer, &QTimer::timeout, this, &QSerialPortPrivate::_q_startAsyncWrite);
startAsyncWriteTimer->setSingleShot(true);
}
if (!startAsyncWriteTimer->isActive())
startAsyncWriteTimer->start();
}
return maxSize;
}
readData
方法不使用定时器,而是直接调用ReadFileEx
。
与仅调用 WriteFileEx
相比,单次计时器完成了什么?
间隔为 0 的 QTimer
有一个特殊情况:一旦控制 returns 到 event loop. The implementation on Unix/Linux does something similar,该计时器将触发,但不使用 QTimer,而是使用QSocketNotifier
的子类,当可以写入端口时将被调用。这两种实现都意味着您将缓冲数据并在返回主事件循环后将其写出。
我认为这样做有两个原因:
- POSIX 和 Win32 串行 API 之间存在一些不同之处,需要以这种方式构建代码。据我所知,情况并非如此
- @Mike 在评论中所说:这将允许在写入数据之前对其进行缓冲
缓冲似乎是最可能的原因,因为对您要写入的每条数据执行系统调用将是一项相当昂贵的操作。