[Development] [QIODevice]How to correctly treat/understand of the documentation?

Carlos Duclos carlosduclosv at yahoo.com
Tue Apr 22 20:13:00 CEST 2014


> Hi Thiago, Kuba,

>
>
>> It should support the same waitForBytesWritten() and waitForReadyRead() that
>> QAbstractSocket and QProcess have. Those are blocking.

>Yes, QSerialPort does it (at least tries to do). :)

>>Let's make sure we distinguish blocking from buffered. It's quite ok for
>>QSerialPort to be unbuffered -- there's a QIODevice flag for it. But it
should
>>still be non-blocking.

>Yes, in the future we will try to add this opportunity. But I don't see
>advantage of Unbuffered mode against Buffered. Because in Unbuffered a mode
>is probable loss of data, because the FIFO can be overflowed and so on. >At
>least this can be occured at reading of data.

If the implementation is sane, there should not be any loss of data regardless of the presence of a buffer or not. Notice that it involves the user of the class too, since the ultimate decision about how to use the class is with him/her.

Look at the read/write calls in Unix. If you use the asynchronous mode of operation you will get an error if the data cannot be read/written. No data is lost, unless you explicitly delete the data you pass to those functions. And from your point of view there is no way to tell if read/write failed because of a empty/full OS buffer or if it is because of a device buffer that is empty/full.

>> Acceptable. It's not how QAbstractSocket and QProcess work, but they
>could
>> change to that someday. And QSerialPort can adopt that policy.
>
>But this decision considerably complicates realization and increases
>fragmentation of data (if we speak about Buffered mode). For me this
>invention is doubtful.
>
>For example, let's see on the non-blocking buffered mode at this scenario:
>
>MyClass::foo()
>{
>    dev.write('a');
>    dev.write('b');
>    dev.write('?');
>}
>
>1) In the current implementation of QProcess, QAbstractSocket (I am about
>the "deferred" writing, as currently implemented) everything is fine:
>at shooting of the notifier (with the Tx empty event), we will send at once
>a whole 'abc' package to the device.
>
>There is only one shortcoming: is a some delay between foo() and the
>triggering of notifier (can be it is critical ??).
>But I don't consider it as a shortcoming.
>
>2) An option which offers by Kuba (if I correctly understood). It is
>"direct" writing to the device if it is ready for writing (e.g. when Tx
>FIFO is empty).
>But in this case we got an fragmentation of data. Because each of
>write('a'), write('b'), write('c') will write data directly to the device
>(in case the Tx FIFO can be filled).
>I don't know as it will affect Unix platforms, but on Windows it is a sheer
>hell. Because there each WriteFile() is separate I/O operation with
>separate OVERLAPPED structure. And each completion of each >overlapped
>operation will be fired and led to loading of CPU.
>

There is so much you can do to prevent a user to misuse your class. If the user wants to use three separate calls to send data that is time sensitive, then so be it.

On the other hand, even if the class does not allow the user to do bad things, the OS might introduce delays that are beyond your control. As long as you use the layers provided by the OS, there is always the chance that data might not be sent when you expected it to be sent.

>Concerning to QSerialPort we can't refuse from overlapped operations. >We
>use it completion to emitting the bytesWritten() and so on.
>
>Thus, I don't see advantage of Kuba offer's against to the current
>QAbstractSocket, QProcess, etc implementation for Buffered mode. >Maybe it
>has sense in Unbuffered mode, I don't know (or maybe I do not >understand
>correctly).
>

I think you should separate the implementations. Most Unixes are able to handle asynchronous operations without much fuzz, so you could have your own qserialport_unix.cpp and have a different one for windows qserialport_win.cpp. Do what's right on Unix and do what's right on Windows. If for some reason there are things that cannot be done on both, be honest and document those.

>
>
>UPD:
>If to be honest, I don't agree with implementation with emission of the
>bytesWritten() signal in QAbstractSocket. IMHO, this signal has to be
>emitted when data were really transferred, i.e. after completion of
>transfer, when fired the Tx-empty notifier. But not after the calling of
>non-blocking write(fd, ..). Probably, for high-speed interfaces (like
>sockets) it is noncritical, but for the serial port it is critical. Because
>exist, for example, the hardware RS-485 devices where the direction of
>transfer is switched by DTR signal. Thus, it is important to know when >data
>transmission is really finished to switch to reception. For this purpose it
>is possible to use bytesWritten(qint64) signal. BUT, in case same
>implementation as in QAbstractSocket, we got an fail, because
>bytesWritten() will tell lies to us.

I think you are making things too complicated. There is no reliable way to know that the data was sent by the device, unless the device explicitly raises a signal after the data is sent. This is dependent on the driver, at least on Linux (and probably other Unixes too). It seems to me that the best course of action for you would be to use asynchronous IO at the OS level and use wait for the OS signals. This will work at least on Linux and most Unixes. On Windows things might be different but I doubt that Windows does not offer something similar in one way or another.

PS1 Where could I take a look at your code?
PS2 Do you have an internal mailing list for the QSerialPort project?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20140422/202d8c2c/attachment.html>


More information about the Development mailing list