Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Thiago, many thanks for your time. :) UPD: Now, we will continue discussion about QtSerialPort in google groups: https://groups.google.com/forum/#!forum/qtserialport Please, who has any ideas and questions, you can join there. BR, Denis 2014-04-29 19:19 GMT+04:00 Thiago Macieira thiago.macie...@intel.com: Em ter 29 abr 2014, às 19:16:51, Denis Shienkov escreveu: Yes. Except that you're referring to non-existent unbuffered modes of QTcpSocket and QProcess... Ok, then what is it This code is for the new Unbuffered QTcpSocket use case? https://qt.gitorious.org/qt/qtbase/source/eb211d74cc3dbf991093ad2e799370f0 06de8198:src/network/socket/qabstractsocket.cpp#L2453 It's not public API. It exists solely for QNAM and comes with the warning here there be dragons. :-) -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em qua 30 abr 2014, às 12:32:42, Denis Shienkov escreveu: Thiago, many thanks for your time. :) UPD: Now, we will continue discussion about QtSerialPort in google groups: https://groups.google.com/forum/#!forum/qtserialport Please, who has any ideas and questions, you can join there. Please note that QtSerialPort is part of Qt and therefore uses this mailing list for development questions. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi Thiago, No, it isn't. The socket notifier activates when there's buffer available in the kernel, not that the buffer is empty. That means something got flushed, but it does not indicate that everything did. I will ask very specifically: what ioctl or fcntl do you need to enable to get the notification? If you don't know the answer to this, I assert that you don't have a tx-empty event. Hmm.. yes, in documentation it so. But actually it event triggered when FIFO is empty. Well, ok, it isn't important, lets skip this issue now.. :) The behaviour of QTcpSocket on all platforms and of QProcess on Unix. Well, thanks a lot. I will take these arguments into account and we will think what to do farther. UPD: Guys, many thanks BR, Denis 2014-04-28 20:25 GMT+04:00 Thiago Macieira thiago.macie...@intel.com: Em seg 28 abr 2014, às 17:04:31, Denis Shienkov escreveu: Hi Thiago, By the way, what is that tx-empty event? E.g., it is an signal of QSocketNotifier::activated(fd) for the Write type of notifier. No, it isn't. The socket notifier activates when there's buffer available in the kernel, not that the buffer is empty. That means something got flushed, but it does not indicate that everything did. I will ask very specifically: what ioctl or fcntl do you need to enable to get the notification? If you don't know the answer to this, I assert that you don't have a tx-empty event. For example, all classes using of the QPipeWriter (QProcess??, QLocalSocket) in Windows implement an true bytesWritten() signal. When the bytesWritten() is emitted after each I/O completion (at least, it got an numbers of transferred bytes after each completion and accumulate it). The Windows behaviour is only that because of either: a) a bug b) the Windows kernel keeps referring to our buffer and we can't completely flush it until we get the completion notification But on other platforms (on *nix) it isn't implemented by a similar method (since in principle there is no asynchronous I/O in *nix). Therefore there bytesWritten() signal is emitted without waiting for the fact of real sending of data. Thus, the same QProcess or QLocalSocket will behave differently on different platforms (I told it already in previous mails). This is the expected behaviour. So, what behavior should I take as basic for the the same as QTcpSocket and QProcess. ? Behavior of QProcess from the Windows platform, or behavior of QProcess from the *nix platform? :) The behaviour of QTcpSocket on all platforms and of QProcess on Unix. For me it is more pleasant, simpler, more logical, to implement a common behavior (for any platform) as in Windows. Because in other case, the bytesWritten() loses the sense; becomes a ballast which doesn't bear the useful sense. That rests on the requirement that the behaviour you want to implement can be implemented. I have not seen any indication so far that it is possible for serial ports, let alone for sockets and pipes. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
.) If we have to rename, I support Thiago's suggestion of Complex input methods, possibly with a text or language thrown in. [Apology in advance for small rant.] In the future, could we please not rename components silently without warning? This renaming effectively edited several of my tasks, making them misleading. As a bonus it also messed up my filters. - Paul ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development -- Message: 4 Date: Mon, 28 Apr 2014 10:59:29 +0200 From: Paul Olav Tvete paul.tv...@digia.com Subject: Re: [Development] Updating JIRA components relating to events. To: development@qt-project.org Message-ID: 2441161.FSKxQZWCL6@neverwhere Content-Type: text/plain; charset=us-ascii On Monday 28 April 2014 08:42:48 Blasche Alexander wrote: I renamed it on request. It was such a minor change that I didn't see an issue especially since the component doesn't have a default assignee. Obviously that is not the case. No worries :) I may be using the components in a slightly non-standard fashion, but I do like to add additional components to tasks, instead of using one component and several labels. In this case, I used the combination of QtPorts: Android and input methods to track the input method issues on Android. - Paul -- Message: 5 Date: Mon, 28 Apr 2014 11:00:31 +0200 From: Nils Jeisecke njeise...@saltation.de Subject: Re: [Development] Question about Qt's future To: Hartmann Thomas thomas.hartm...@digia.com Cc: development@qt-project.org development@qt-project.org Message-ID: CANh_-9dOkhoHLK9AkYDO4ga1Py95Vx5h3=c-7sdkantzm7r...@mail.gmail.com Content-Type: text/plain; charset=UTF-8 Hi, Another idea is to allow C++ companion objects, that would take the place of any Java Script code for people who prefer C++. A companion object would be a QObject paired with the QML object, that has access to the QML context. The QObject would then define a couple of signals/slots that can be used from QML as Java Script is used today. I really like this idea. Maybe one could even write C++ code directly in the QML file and let a preprocessor generate a proper C++ class containing this code. So, no more JavaScript, data conversion and garbage collection. Or just another tooling nightmare? Nils -- Message: 6 Date: Mon, 28 Apr 2014 11:16:27 +0200 From: Oswald Buddenhagen oswald.buddenha...@digia.com Subject: Re: [Development] [QIODevice]How to correctly treat/understand of the documentation? To: development@qt-project.org Message-ID: 20140428091627.ga5...@troll08.it.local Content-Type: text/plain; charset=iso-8859-1 On Sun, Apr 27, 2014 at 01:34:52PM -0700, Thiago Macieira wrote: Em dom 27 abr 2014, ?s 11:08:44, Denis Shienkov escreveu: Here I am a little disagree. Because in Unbuffered mode, loss of data is exists. For example, in a case when the port accepts a data stream. And when the user ignores readyRead() signal, i.e do not reads nothing from port. In this case FIFO of device/driver will be overflowed, that will cause overrun/overflow errors, and part of stream will be lost. Doesn't happen with pipes, sockets and other devices with flow control. yeah, but serial ports can be operated without flow control. if the kernel does not buffer indefinitely (which seems plausible, as otherwise one could DoS it), data could be discarded indeed. As I wrote above, the only Windows has an true async I/O. The Unix has not this feature, he has only non-blocking approach, but it is not an async I/O. So, implementation of completion of I/O operation is problematic on any Unix's. We only can judge about operation completion indirectly, e.g. for writing - wait for the Tx-empty event. By the way, what is that tx-empty event? Note that sockets and pipes don't have that, so please don't make QSerialPort use that by default. You can add an extra signal to QSerialPort to indicate this, but bytesWritten() must mean the same as QTcpSocket and QProcess. a separate signal would be redundant, as checking byteToWrite() == 0 in the slot called from bytesWritten() is sufficient. -- Message: 7 Date: Mon, 28 Apr 2014 09:32:12 + From: Hartmann Thomas thomas.hartm...@digia.com Subject: Re: [Development] Question about Qt's future To: Nils Jeisecke njeise...@saltation.de Cc: development@qt-project.org development@qt-project.org Message-ID: 1380ceabc81b604bbd1cbde7c61f9401cf1...@it-exmb01-hki.it.local Content-Type: text/plain; charset=us-ascii Hi, yes, writting C++ inline in QML would be another tooling nightmare. Also what is the problem with: MouseArea { onClicked: companion.mouseAreaClicked(); } If tooling creates the companion
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em ter 29 abr 2014, às 12:48:55, Denis Shienkov escreveu: This is expected behavior? Yes. Except that you're referring to non-existent unbuffered modes of QTcpSocket and QProcess... -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
2014-04-29 19:13 GMT+04:00 Denis Shienkov denis.shien...@gmail.com: Yes. Except that you're referring to non-existent unbuffered modes of QTcpSocket and QProcess... Ok, then what is it This code is for the new Unbuffered QTcpSocket use case? https://qt.gitorious.org/qt/qtbase/source/eb211d74cc3dbf991093ad2e799370f006de8198:src/network/socket/qabstractsocket.cpp#L2453 :) BR, Denis 2014-04-29 18:52 GMT+04:00 Thiago Macieira thiago.macie...@intel.com: Em ter 29 abr 2014, às 12:48:55, Denis Shienkov escreveu: This is expected behavior? Yes. Except that you're referring to non-existent unbuffered modes of QTcpSocket and QProcess... -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em ter 29 abr 2014, às 19:16:51, Denis Shienkov escreveu: Yes. Except that you're referring to non-existent unbuffered modes of QTcpSocket and QProcess... Ok, then what is it This code is for the new Unbuffered QTcpSocket use case? https://qt.gitorious.org/qt/qtbase/source/eb211d74cc3dbf991093ad2e799370f0 06de8198:src/network/socket/qabstractsocket.cpp#L2453 It's not public API. It exists solely for QNAM and comes with the warning here there be dragons. :-) -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
On Sun, Apr 27, 2014 at 01:34:52PM -0700, Thiago Macieira wrote: Em dom 27 abr 2014, às 11:08:44, Denis Shienkov escreveu: Here I am a little disagree. Because in Unbuffered mode, loss of data is exists. For example, in a case when the port accepts a data stream. And when the user ignores readyRead() signal, i.e do not reads nothing from port. In this case FIFO of device/driver will be overflowed, that will cause overrun/overflow errors, and part of stream will be lost. Doesn't happen with pipes, sockets and other devices with flow control. yeah, but serial ports can be operated without flow control. if the kernel does not buffer indefinitely (which seems plausible, as otherwise one could DoS it), data could be discarded indeed. As I wrote above, the only Windows has an true async I/O. The Unix has not this feature, he has only non-blocking approach, but it is not an async I/O. So, implementation of completion of I/O operation is problematic on any Unix's. We only can judge about operation completion indirectly, e.g. for writing - wait for the Tx-empty event. By the way, what is that tx-empty event? Note that sockets and pipes don't have that, so please don't make QSerialPort use that by default. You can add an extra signal to QSerialPort to indicate this, but bytesWritten() must mean the same as QTcpSocket and QProcess. a separate signal would be redundant, as checking byteToWrite() == 0 in the slot called from bytesWritten() is sufficient. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi Oswald, a separate signal would be redundant, as checking byteToWrite() == 0 in the slot called from bytesWritten() is sufficient. Can you, please, more explain of your idea? BR, Denis 2014-04-28 13:16 GMT+04:00 Oswald Buddenhagen oswald.buddenha...@digia.com : On Sun, Apr 27, 2014 at 01:34:52PM -0700, Thiago Macieira wrote: Em dom 27 abr 2014, às 11:08:44, Denis Shienkov escreveu: Here I am a little disagree. Because in Unbuffered mode, loss of data is exists. For example, in a case when the port accepts a data stream. And when the user ignores readyRead() signal, i.e do not reads nothing from port. In this case FIFO of device/driver will be overflowed, that will cause overrun/overflow errors, and part of stream will be lost. Doesn't happen with pipes, sockets and other devices with flow control. yeah, but serial ports can be operated without flow control. if the kernel does not buffer indefinitely (which seems plausible, as otherwise one could DoS it), data could be discarded indeed. As I wrote above, the only Windows has an true async I/O. The Unix has not this feature, he has only non-blocking approach, but it is not an async I/O. So, implementation of completion of I/O operation is problematic on any Unix's. We only can judge about operation completion indirectly, e.g. for writing - wait for the Tx-empty event. By the way, what is that tx-empty event? Note that sockets and pipes don't have that, so please don't make QSerialPort use that by default. You can add an extra signal to QSerialPort to indicate this, but bytesWritten() must mean the same as QTcpSocket and QProcess. a separate signal would be redundant, as checking byteToWrite() == 0 in the slot called from bytesWritten() is sufficient. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em seg 28 abr 2014, às 11:16:27, Oswald Buddenhagen escreveu: On Sun, Apr 27, 2014 at 01:34:52PM -0700, Thiago Macieira wrote: yeah, but serial ports can be operated without flow control. if the kernel does not buffer indefinitely (which seems plausible, as otherwise one could DoS it), data could be discarded indeed. Right. But it's the application's responsibility to read everything in a timely manner, regardless of whether buffering is enabled or not. If it's not enabled, there could be data loss or blockage of the other side due to flow control. If it is enabled, you need to read to avoid blowing up the buffers. By the way, what is that tx-empty event? Note that sockets and pipes don't have that, so please don't make QSerialPort use that by default. You can add an extra signal to QSerialPort to indicate this, but bytesWritten() must mean the same as QTcpSocket and QProcess. a separate signal would be redundant, as checking byteToWrite() == 0 in the slot called from bytesWritten() is sufficient. I don't think that's what Denis wanted. He wants to know when the kernel buffer is empty, not just Qt's. That is, when the data was sent over the serial line, without verification that the other side actually received it (with a long cable, it could take several microseconds or even milliseconds for the other side to receive). -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em seg 28 abr 2014, às 17:04:31, Denis Shienkov escreveu: Hi Thiago, By the way, what is that tx-empty event? E.g., it is an signal of QSocketNotifier::activated(fd) for the Write type of notifier. No, it isn't. The socket notifier activates when there's buffer available in the kernel, not that the buffer is empty. That means something got flushed, but it does not indicate that everything did. I will ask very specifically: what ioctl or fcntl do you need to enable to get the notification? If you don't know the answer to this, I assert that you don't have a tx-empty event. For example, all classes using of the QPipeWriter (QProcess??, QLocalSocket) in Windows implement an true bytesWritten() signal. When the bytesWritten() is emitted after each I/O completion (at least, it got an numbers of transferred bytes after each completion and accumulate it). The Windows behaviour is only that because of either: a) a bug b) the Windows kernel keeps referring to our buffer and we can't completely flush it until we get the completion notification But on other platforms (on *nix) it isn't implemented by a similar method (since in principle there is no asynchronous I/O in *nix). Therefore there bytesWritten() signal is emitted without waiting for the fact of real sending of data. Thus, the same QProcess or QLocalSocket will behave differently on different platforms (I told it already in previous mails). This is the expected behaviour. So, what behavior should I take as basic for the the same as QTcpSocket and QProcess. ? Behavior of QProcess from the Windows platform, or behavior of QProcess from the *nix platform? :) The behaviour of QTcpSocket on all platforms and of QProcess on Unix. For me it is more pleasant, simpler, more logical, to implement a common behavior (for any platform) as in Windows. Because in other case, the bytesWritten() loses the sense; becomes a ballast which doesn't bear the useful sense. That rests on the requirement that the behaviour you want to implement can be implemented. I have not seen any indication so far that it is possible for serial ports, let alone for sockets and pipes. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi Carlos. 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. Here I am a little disagree. Because in Unbuffered mode, loss of data is exists. For example, in a case when the port accepts a data stream. And when the user ignores readyRead() signal, i.e do not reads nothing from port. In this case FIFO of device/driver will be overflowed, that will cause overrun/overflow errors, and part of stream will be lost. Of course, the user shall take responsibility for processing in Unbuffered mode. But I think that Unbuffered mode isn't necessary. What sense in it? What advantages? So, I think, that the Buffered mode it is sufficient way. When all data reads from FIFO and stored into internal buffer of class, then no exists data loss. 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. Then class implementation significantly becomes complicated (and maybe impossible). Probably, the way with separate write() for the minimum time delay can be implemented for Unbuffered mode. i.e. using of Unbuffered mode will be recommended if the User want to use minimal delays and direct I/O. 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. Please see QtSerialPort sources.. BTW: The asynchronous I/O in Unix (POSIX) has a big problems against Windows. Maybe it is make sense to use aio_read/aio_write instead of read/write syscalls for *nix. 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. As I wrote above, the only Windows has an true async I/O. The Unix has not this feature, he has only non-blocking approach, but it is not an async I/O. So, implementation of completion of I/O operation is problematic on any Unix's. We only can judge about operation completion indirectly, e.g. for writing - wait for the Tx-empty event. PS1 Where could I take a look at your code? https://qt-project.org/wiki/QtSerialPort PS2 Do you have an internal mailing list for the QSerialPort project? No, we don't have it. BR, Denis 22.04.2014 22:13, Carlos Duclos ?: 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
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em dom 27 abr 2014, às 11:08:44, Denis Shienkov escreveu: Here I am a little disagree. Because in Unbuffered mode, loss of data is exists. For example, in a case when the port accepts a data stream. And when the user ignores readyRead() signal, i.e do not reads nothing from port. In this case FIFO of device/driver will be overflowed, that will cause overrun/overflow errors, and part of stream will be lost. Doesn't happen with pipes, sockets and other devices with flow control. Of course, the user shall take responsibility for processing in Unbuffered mode. But I think that Unbuffered mode isn't necessary. What sense in it? What advantages? So, I think, that the Buffered mode it is sufficient way. When all data reads from FIFO and stored into internal buffer of class, then no exists data loss. True. We don't offer unbuffered mode for QTcpSocket or QProcess either. As I wrote above, the only Windows has an true async I/O. The Unix has not this feature, he has only non-blocking approach, but it is not an async I/O. So, implementation of completion of I/O operation is problematic on any Unix's. We only can judge about operation completion indirectly, e.g. for writing - wait for the Tx-empty event. By the way, what is that tx-empty event? Note that sockets and pipes don't have that, so please don't make QSerialPort use that by default. You can add an extra signal to QSerialPort to indicate this, but bytesWritten() must mean the same as QTcpSocket and QProcess. PS2 Do you have an internal mailing list for the QSerialPort project? No, we don't have it. Well, yes you do. It's this one :-) -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
On Apr 22, 2014, at 12:10 PM, Thiago Macieira thiago.macie...@intel.com wrote: Em ter 22 abr 2014, às 19:34:48, Denis Shienkov escreveu: 1. or keep it as is, but then bytesWritten() will be tell lies It's not lying. It's telling the user that the bytes were written from the QIODevice to the underlying device. That's the best we can do, since now those bytes are no longer under our control. I fully agree with this assessment. Many platforms don’t even provide any means of notification that a physical transmit buffer is empty. They could, but they don’t. RS-485 direction switching needs to be done at the driver level, not in the userland, unless the userland implements the driver. So this is possible for user-mode USB drivers. Incidentally, my experience with user-mode drivers is much better than with kernel drivers, especially for “serial-like” devices. I think that QSerialPort should provide abstract base classes that could be reimplemented for various types of hardware. For me, the FTDI devices work much better on Linux and OS X with self-written user-mode drivers where I have full control over what’s going on. Incidentally, I have notifications of the USB transactions being finished, and of the device FIFOs emptying. I could do software DTR switching if I needed it. Using stock drivers it’s impossible. I only use it for diagnostics, though. Cheers, Kuba Ober ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi Kuba, The `QSerialPort` API must be nonblocking, It is truth, currently it is non-blocking. The writes should be executed right away if they won’t block. The semantics would be: There are some problems, please see below: 1. Check how many bytes can be written to the OS device buffers without blocking. In most cases it is impossible since OS doesn't provide such API. There is only API by means of which it is possible to receive number of bytes in Tx FIFO of device (ready to transfer). But a problem what not all producers/vendors of drivers of serial ports implements this API. Therefore it is impossible to rely on this API and to be sure of it for 100%. 2a. If the buffer is empty, write as many bytes as possible from the data given to write, add remainder to the buffer. 2b. If the buffer is non-empty, append the data to the buffer, and drain as much of the buffer as possible. It is the continue of the same situation from the item №1 - impossible be implemented. The reads should be executed right away if they wouldn’t block. The semantics would be: This also has some limitations: 1. Check how many bytes can be read from the OS device buffers without blocking. Also, not all vendors of devices implements in a drivers these possibilities of receiving number of bytes in Rx FIFO of device (which ready to read). Even if we assume, that this API is implemented, then this system call is the additional loading on CPU, we need to avoid it. Currently at data reading is applied an some cunning. We don't get number of bytes in Rx FIFO (it isn't necessary for us). We simply read from Rx FIFO some fixed pieces (on 512 bytes) of data. For example, in Rx FIFO came 15 bytes, further, the Rx event shoots and we call read(512). In this case the read() will return 15 bytes which we add to the buffer. Of course, all this occurs inside of QSerialPort and is invisible for the user. Everything made is asynchronously and in non-blocking mode. When the user will call QSerialPort::read(), then the QSerialPort will return data from the internal buffer immediately. I will repeat once again: at present, the QSerialPort always works in asynchronously (in non-blocking mode) and in the buffered mode. At present, there I/O are no problems in principle. Problems begin at implementation of the waifForReadyRead(), waitForBytesWritten(), flush() methods. And also bytesWritten() signal. Because IMHO, there is no accurate specification and their behavior can be implemented in various ways. BR, Denis 2014-04-21 22:31 GMT+04:00 Thiago Macieira thiago.macie...@intel.com: Em seg 21 abr 2014, às 14:21:24, Kuba Ober escreveu: Essentially, there’s only *two* changes I’d like to see in QSerialPort’s implementation. These changes may not be possible to implement on all platforms, of course. The `QSerialPort` API must be nonblocking, that’s the whole point of having it to start with. Doing blocking reads/writes is trivial using platform APIs - I don’t think QSerialPort should support any blocking operations. It should support the same waitForBytesWritten() and waitForReadyRead() that QAbstractSocket and QProcess have. Those are blocking. 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. The only constraint that puts is on non-buffered writing. The waitForBytesWritten() function operates on the buffered bytes. You may want to add a waitForReadyWrite() for the unbuffered case. Internally I use classes that behave that way and they work as well as anything in userspace can ever work, given that the code must be non-blocking. The writes should be executed right away if they won’t block. The semantics would be: 1. Check how many bytes can be written to the OS device buffers without blocking. Acceptable. It's not how QAbstractSocket and QProcess work, but they could change to that someday. And QSerialPort can adopt that policy. 2a. If the buffer is empty, write as many bytes as possible from the data given to write, add remainder to the buffer. 2b. If the buffer is non-empty, append the data to the buffer, and drain as much of the buffer as possible. The reads should be executed right away if they wouldn’t block. The semantics would be: 1. Check how many bytes can be read from the OS device buffers without blocking. 2. Get everything from the OS queue and append to the buffer. 3. Drain as much of the buffer as requested in the argument to `read` and return to the user. QIODevice already does that: if the buffer is non-empty, it drains the buffer. If the buffer becomes empty and the user still wants more data, it calls readData(). QAbstractSocket and QProcess do not read from the OS device in readData() though. So that readData() used to read from a second buffer in older Qt versions -- now, it doesn't do
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
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. 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. 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). 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. Example: QWindowsPipeWriter. It has to be re-implemented to IO Completion Port instead of thousands of threads. :) BR, Denis 2014-04-22 11:33 GMT+04:00 Denis Shienkov denis.shien...@gmail.com: Hi Kuba, The `QSerialPort` API must be nonblocking, It is truth, currently it is non-blocking. The writes should be executed right away if they won’t block. The semantics would be: There are some problems, please see below: 1. Check how many bytes can be written to the OS device buffers without blocking. In most cases it is impossible since OS doesn't provide such API. There is only API by means of which it is possible to receive number of bytes in Tx FIFO of device (ready to transfer). But a problem what not all producers/vendors of drivers of serial ports implements this API. Therefore it is impossible to rely on this API and to be sure of it for 100%. 2a. If the buffer is empty, write as many bytes as possible from the data given to write, add remainder to the buffer. 2b. If the buffer is non-empty, append the data to the buffer, and drain as much of the buffer as possible. It is the continue of the same situation from the item №1 - impossible be implemented. The reads should be executed right away if they wouldn’t block. The semantics would be: This also has some limitations: 1. Check how many bytes can be read from the OS device buffers without blocking. Also, not all vendors of devices implements in a drivers these possibilities of receiving number of bytes in Rx FIFO of device (which ready to read). Even if we assume, that this API is implemented, then this system call is the additional loading
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em ter 22 abr 2014, às 12:28:39, Denis Shienkov escreveu: 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. That's simply not workable. If the buffer never empties, bytesWritten() would never fire. Imagine the user is always writing data at the same speed as the device is transmitting (or faster). -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi Thiago, That's simply not workable. If the buffer never empties, bytesWritten() would never fire. Imagine the user is always writing data at the same speed as the device is transmitting (or faster). Hmm.. Yes. But this scenario it is possible in case of continuous flushing (or, maybe with waitForBytesWritten(), not sure). Because only the flushing can adds data to the FIFO of driver directly , e.g: connect(timer, SIGNAL(timeout()), this, SLOT(fooSlot())); MyClass::fooSlot() { dev.write(); dev.write(); dev.write(); dev.flush(); } where an timer has an zero (0) interval (for example to continuous writing) and only on POSIX-compatible platforms.In other cases (and on Windows with using overlapped I/O it will be fine), IMHO. So, here are dilemma: 1. or keep it as is, but then bytesWritten() will be tell lies 2. or modify it (as I offer), but then bytesWritten() can never fired (as you say) It is bad. Because (concerning to QSerialPort) if to keep as is, then implementation of bytesWritten() in Windows will be correctly work, but implementation in POSIX will be lies... i.e. we can't get an identical behavior on different platforms anyway, i.e. the user can be confused. Bad bad bad... :) BR, Denis 2014-04-22 18:42 GMT+04:00 Thiago Macieira thiago.macie...@intel.com: Em ter 22 abr 2014, às 12:28:39, Denis Shienkov escreveu: 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. That's simply not workable. If the buffer never empties, bytesWritten() would never fire. Imagine the user is always writing data at the same speed as the device is transmitting (or faster). -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em ter 22 abr 2014, às 19:34:48, Denis Shienkov escreveu: 1. or keep it as is, but then bytesWritten() will be tell lies It's not lying. It's telling the user that the bytes were written from the QIODevice to the underlying device. That's the best we can do, since now those bytes are no longer under our control. Think about it. How do we know that the bytes were actually sent? What happens if the cable is torn? Next, we'd have users asking for confirmation that the other side received the data, which we can't provide. And even if the other side did receive the data (we can tell with TCP), we can't confirm that the application received the data. And even if it did read the data, there's no telling whether it acted on the data. So, no, we provide details about the data we control, at the level we control. QIODevice has a buffer and bytesWritten informs about bytes being written from that buffer. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
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
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em ter 22 abr 2014, às 11:13:00, Carlos Duclos escreveu: PS1 Where could I take a look at your code? QtSerialPort is part of Qt since 5.2. https://qt.gitorious.org/qt/qtserialport http://code.woboq.org/qt5/qtserialport/ -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hmmm.. Thiago, what do you mean by writeable? It is when device was opened in the WriteOnly (ReadWrite) mode, or something else? If I correctly understand, then I assume that the device always is writeable: i.e. opened in WriteOnly (ReadWrite) and the internal buffer of writing is not empty. (1) = Without flush ( and the seized moment between foo() and bar(), just for example, as scenario )= MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); } It is supposed that the notifier is fired after foo() and made syscall ::write(fd, 'ab') to the device (device driver), but before bar(). Also, the 'ab' package was not really transferred yet (e.g. in time is transferred only the 'a' part of package) to device, i.e. the Tx FIFO of the driver didn't become empty yet. I.e., there has to be such chain: 1. is called the foo() 2. add 'ab' to internal buffer and enable Tx notification (if was disabled) 3. some idle timeout (work in Qt-event loop) 4. fired the Tx empty event, that Tx FIFO is empty (if FIFO really was empty) 5. write the 'ab' to device (the Tx FIFO of device/driver has 2 bytes) 6. the driver transferring one byte 'a' from the Tx FIFO (the FIFO is decreased by one byte, and still contains the 'b' byte), 7. at this moment it is called the bar() 8. add 'cd' to internal buffer and enable Tx notification (if was disabled) 9. the driver transferring one byte 'b' from the Tx FIFO (the FIFO is decreased by one byte, so, now is empty) 10. some idle timeout (work in Qt-event loop) 11. fired the Tx empty event (again), that Tx FIFO is empty 12. do emitting of the bytesWritten( 2 byte ) signal (for 'ab' package), that an data were *really* transferred 13. write the 'cd' to device (the Tx FIFO of device/driver has 2 bytes) 14. the driver transferring one byte 'c' from the Tx FIFO (the FIFO is decreased by one byte, and still contains the 'd' byte) 15. the driver transferring one byte 'd' from the Tx FIFO (the FIFO is decreased by one byte, so, now is empty) 16. some idle timeout (work in Qt-event loop) 17. fired the Tx empty event (again), that Tx FIFO is empty 18. do emitting of the bytesWritten( 2 byte ) signal (for 'cd' package), that an data were *really* transferred 19. stop Tx notification I correctly describe it behavior? :) (2) = With flush ( and the seized moment between foo() and bar(), just for example, as scenario ) =: MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); dev.flush(); } I.e., there has to be such chain: 1. is called the foo() 2. add 'ab' to internal buffer and enable Tx notification (if was disabled) 3. some idle timeout (work in Qt-event loop) 4. fired the Tx empty event, that Tx FIFO is empty (if FIFO really was empty) 5. write the 'ab' to device (the Tx FIFO of device/driver has 2 bytes) 6. the driver transferring one byte 'a' from the Tx FIFO (the FIFO is decreased by one byte, and still contains the 'b' byte) 7. at this moment it is called the bar() 8. add 'cd' to internal buffer and enable Tx notification (if was disabled) 9. forcibly to write the 'cd' to device (the Tx FIFO of device/driver has 3 bytes), the flush() do it 9. the driver transferring one byte 'b' from the Tx FIFO (the FIFO is decreased by one byte, and still contains the 'cd' bytes) 10. the driver transferring one byte 'c' from the Tx FIFO (the FIFO is decreased by one byte, and still contains the 'd' byte) 11. the driver transferring one byte 'd' from the Tx FIFO (the FIFO is decreased by one byte, so, now is empty) 12. some idle timeout (work in Qt-event loop) 13. fired the Tx empty event (again), that Tx FIFO is empty 14. do emitting of the bytesWritten( 4 byte ) signal (for 'abcd' package), that an data were *really* transferred 15. stop Tx notification I correctly describe it behavior? ;) (3) = With flush ( an delay between foo() and bar() is not seized, just for example, as scenario ) =: MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); dev.flush(); } I.e., there has to be such chain: 1. is called the foo() 2. add 'ab' to internal buffer and enable Tx notification (if was disabled) 3. some idle timeout (work in Qt-event loop) 4. fired the Tx empty event, that Tx FIFO is empty (if FIFO really was empty) 5. write the 'ab' to device (the Tx FIFO of device/driver has 2 bytes) 6. the driver transferring one byte 'a' from the Tx FIFO (the FIFO is decreased by one byte, and still contains the 'b' byte) 7. the driver transferring one byte 'b' from the Tx FIFO (the FIFO is decreased by one byte, so, now is empty) 8. some idle timeout (work in Qt-event loop) 9. fired the Tx empty event (again), that Tx FIFO is empty 10. do emitting of the bytesWritten( 2 byte ) signal (for 'ab' package), that an data were *really* transferred 11. stop Tx notification 12. Some idle period 12. is called the bar() 13. add 'cd' to internal buffer and enable Tx notification
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em seg 21 abr 2014, às 16:50:50, Denis Shienkov escreveu: Hmmm.. Thiago, what do you mean by writeable? It is when device was opened in the WriteOnly (ReadWrite) mode, or something else? When the underlying device can receive more bytes from the userspace. Sockets and pipes are buffered in the kernel. When you write to them, they don't get sent immediately (for sockets, specifically, there's Nagle's algorithm in place). They get buffered and sent later. That buffer is not unlimited in size. When you write too much, the OS will not accept more write() calls. That is, write() will return -EWOULDBLOCK. When that happens, you need the QSocketNotifier for Write to tell you when it's acceptable to write again. QAbstractSocket and QProcess always put the data in their own buffer during writeData(). Then they enable the QSocketNotifier for Write, if it wasn't enabled. When that notifier fires, in the event loop, the actual writing to the OS happens. If I correctly understand, then I assume that the device always is writeable: i.e. opened in WriteOnly (ReadWrite) and the internal buffer of writing is not empty. You assume wrong. Therefore, the rest of the email does not make sense. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Essentially, there’s only *two* changes I’d like to see in QSerialPort’s implementation. These changes may not be possible to implement on all platforms, of course. The `QSerialPort` API must be nonblocking, that’s the whole point of having it to start with. Doing blocking reads/writes is trivial using platform APIs - I don’t think QSerialPort should support any blocking operations. Internally I use classes that behave that way and they work as well as anything in userspace can ever work, given that the code must be non-blocking. The writes should be executed right away if they won’t block. The semantics would be: 1. Check how many bytes can be written to the OS device buffers without blocking. 2a. If the buffer is empty, write as many bytes as possible from the data given to write, add remainder to the buffer. 2b. If the buffer is non-empty, append the data to the buffer, and drain as much of the buffer as possible. The reads should be executed right away if they wouldn’t block. The semantics would be: 1. Check how many bytes can be read from the OS device buffers without blocking. 2. Get everything from the OS queue and append to the buffer. 3. Drain as much of the buffer as requested in the argument to `read` and return to the user. On platforms where there is no non-blocking API for step #1, the read and write is forced to use the buffer only, as it currently does. Cheers, Kuba Ober On Apr 21, 2014, at 12:35 PM, Denis Shienkov denis.shien...@gmail.com wrote: Thiago, many thanks for your help. BR, Denis 21.04.2014 20:12, Thiago Macieira пишет: Em seg 21 abr 2014, às 16:50:50, Denis Shienkov escreveu: Hmmm.. Thiago, what do you mean by writeable? It is when device was opened in the WriteOnly (ReadWrite) mode, or something else? When the underlying device can receive more bytes from the userspace. Sockets and pipes are buffered in the kernel. When you write to them, they don't get sent immediately (for sockets, specifically, there's Nagle's algorithm in place). They get buffered and sent later. That buffer is not unlimited in size. When you write too much, the OS will not accept more write() calls. That is, write() will return -EWOULDBLOCK. When that happens, you need the QSocketNotifier for Write to tell you when it's acceptable to write again. QAbstractSocket and QProcess always put the data in their own buffer during writeData(). Then they enable the QSocketNotifier for Write, if it wasn't enabled. When that notifier fires, in the event loop, the actual writing to the OS happens. If I correctly understand, then I assume that the device always is writeable: i.e. opened in WriteOnly (ReadWrite) and the internal buffer of writing is not empty. You assume wrong. Therefore, the rest of the email does not make sense. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em seg 21 abr 2014, às 14:21:24, Kuba Ober escreveu: Essentially, there’s only *two* changes I’d like to see in QSerialPort’s implementation. These changes may not be possible to implement on all platforms, of course. The `QSerialPort` API must be nonblocking, that’s the whole point of having it to start with. Doing blocking reads/writes is trivial using platform APIs - I don’t think QSerialPort should support any blocking operations. It should support the same waitForBytesWritten() and waitForReadyRead() that QAbstractSocket and QProcess have. Those are blocking. 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. The only constraint that puts is on non-buffered writing. The waitForBytesWritten() function operates on the buffered bytes. You may want to add a waitForReadyWrite() for the unbuffered case. Internally I use classes that behave that way and they work as well as anything in userspace can ever work, given that the code must be non-blocking. The writes should be executed right away if they won’t block. The semantics would be: 1. Check how many bytes can be written to the OS device buffers without blocking. Acceptable. It's not how QAbstractSocket and QProcess work, but they could change to that someday. And QSerialPort can adopt that policy. 2a. If the buffer is empty, write as many bytes as possible from the data given to write, add remainder to the buffer. 2b. If the buffer is non-empty, append the data to the buffer, and drain as much of the buffer as possible. The reads should be executed right away if they wouldn’t block. The semantics would be: 1. Check how many bytes can be read from the OS device buffers without blocking. 2. Get everything from the OS queue and append to the buffer. 3. Drain as much of the buffer as requested in the argument to `read` and return to the user. QIODevice already does that: if the buffer is non-empty, it drains the buffer. If the buffer becomes empty and the user still wants more data, it calls readData(). QAbstractSocket and QProcess do not read from the OS device in readData() though. So that readData() used to read from a second buffer in older Qt versions -- now, it doesn't do anything. On platforms where there is no non-blocking API for step #1, the read and write is forced to use the buffer only, as it currently does. Not exactly true. If you don't have a non-blocking API, you need threads. Buffers alone don't help you. Example: QWindowsPipeWriter. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Thiago, many thanks for your time and answers. Forgive for my importunity, but I shall ask also about following: == Second issue == What about two scenarios ? (e.g. for some abstract I/O device): 1) Without flush(): MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); } when, the bar() method were called after the foo(), when the Qt-event loop was entered after foo(). i.e. for example both foo() and bar() are the buttons-clicked-handlers. then I expected to receive two: bytesWritten(2 byte) + bytesWritten(2 byte) signals 2) With flush(): MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); dev.flush(); } when, the bar() method were called after foo() (with some delay), but when not all data (a and b) was written (e.g. was in time written only a). i.e. for example both foo() and bar() are the buttons-clicked-handlers, but the bar-button-clicked in the moment when not all data was written from the previous foo-button-clicked. then I expected to receive one bytesWritten(4 byte) signal 3) With double flush(): MyClass::foo() { dev.write('a'); dev.write('b'); dev.flush(); } MyClass::bar() { dev.write('c'); dev.write('d'); dev.flush(); } what here I expect to receive after all data will be really transferred? to receive two: bytesWritten(2 byte) + bytesWritten(2 byte) signals, or to receive one bytesWritten(4 byte) signal ? Can you please comment it? What behaviour should be implemented for these three scenarios? This question also causes many disputes since it is ambiguous. :( BR, Denis 19.04.2014 12:13, Thiago Macieira пишет: Em sáb 19 abr 2014, às 10:42:27, Denis Shienkov escreveu: But still I didn't receive the concrete response: as to us to be? In a buffer mode is to use the deferred writing or the immediately writing? You choose. If you choose to write immediately in writeData(), justify. Otherwise, follow existing practice. The following classes always buffer: - QProcess - QLocalSocket - QAbstractSocket - QSslSocket Similarly, none of the classes above and neither QNetworkReply actually read from the device in readData(). They only read from the buffer. I haven't looked at what QWebSocket does. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em dom 20 abr 2014, às 22:13:47, Denis Shienkov escreveu: == Second issue == What about two scenarios ? (e.g. for some abstract I/O device): 1) Without flush(): MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); } when, the bar() method were called after the foo(), when the Qt-event loop was entered after foo(). i.e. for example both foo() and bar() are the buttons-clicked-handlers. then I expected to receive two: bytesWritten(2 byte) + bytesWritten(2 byte) signals That might not happen. It depends on whether the underlying device was writeable in the meantime and that the socket notifier did fire. 2) With flush(): MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); dev.flush(); } when, the bar() method were called after foo() (with some delay), but when not all data (a and b) was written (e.g. was in time written only a). i.e. for example both foo() and bar() are the buttons-clicked-handlers, but the bar-button-clicked in the moment when not all data was written from the previous foo-button-clicked. then I expected to receive one bytesWritten(4 byte) signal flush() does not guarantee that any data gets written. It s equivalent to waitForBytesWritten(0), which will not write anything if the device is not writeable. And it won't block waiting for it to become writeable. 3) With double flush(): MyClass::foo() { dev.write('a'); dev.write('b'); dev.flush(); } MyClass::bar() { dev.write('c'); dev.write('d'); dev.flush(); } what here I expect to receive after all data will be really transferred? to receive two: bytesWritten(2 byte) + bytesWritten(2 byte) signals, or to receive one bytesWritten(4 byte) signal ? Either is fine. See above: flush() does not guarantee that data gets written, since it won't block. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi Thiago, many thanks for your answer.. == First issue == But still I didn't receive the concrete response: as to us to be? :) In a buffer mode is to use the deferred writing or the immediately writing? This question causes many disputes in our QtSerialPort team ( even, up to a fight :) ). For example, I insist on deferred, other members of team, e.g. on immediately. Unfortunately, we can't come to a consensus in this question. == Second issue == What about two scenarios ? (e.g. for some abstract I/O device): 1) Without flush(): MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); } when, the bar() method were called after foo() (with some delay), but when not all data (a and b) was written (e.g. was in time written only a). then I expected to receive two: bytesWrittenSignal(2 byte) + bytesWrittenSignal(2 byte) 2) With flush(): MyClass::foo() { dev.write('a'); dev.write('b'); } MyClass::bar() { dev.write('c'); dev.write('d'); dev.flush(); } when, the bar() method were called after foo() (with some delay), but when not all data (a and b) was written (e.g. was in time written only a). then I expected to receive one bytesWrittenSignal(4 byte) Whether correctly I understandаnd for expected behavior? Or, I'm wrong? This question also causes many disputes since it is ambiguous. BR, Denis 18.04.2014 19:01, Thiago Macieira пишет: Em sex 18 abr 2014, às 18:14:43, Denis Shienkov escreveu: Hi. I once again fluently look source codes of Qt and I see that the only one I/O class which supports a buffered mode is QTcpSocket (i.e. QAbstractSocket in buffered mode); in which is used the deferred writing for data transfer. Thus, whether can I take such behavior (with deferred writing) as a basis for implementation of I/O in QtSerialPort where only buffered mode is used (as in QTcpSocket) ? Because I don't see other precedents and examples which to take as a basis. QProcess is also like that. In both cases, the underlying I/O mechanism cannot take unlimited amounts of data. The OS will only receive a certain number of bytes from the application before saying no more. So the writeData() functions for those two classes must be able to buffer everything that can't be written immediately. Why it doesn't write immediately, I don't know. It was like that when I arrived in 2006. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi Carlos, Disclaimer. I don't work for Digia and I have never worked for Digia. I did work for Trolltech and Nokia though. Ahh, clear. Thx. I think you are starting from the wrong end. The question is not if you should support one mode of operation or the other, that needs to be analyzed case by case. IMHO you should implement both modes of operation and let the user decide which one to use by specifying the right flags at open time. Yes, I agree. In the future we will add Unbuffered mode, but that isn't the in this question. Because I talk about Buffered mode only. I think I disagree with that statement. This is not a very important part of the project, it is an implementation detail. No. These details cause rough disputes between members of team. :) Thus it is necessary accurately and to be defined specifically, what behavior we expect. Because implementation and behavior depends on it. And other methods: write(), flush(), waitForXX(), bytesWritten() signal and etc, also depends on it, I.e. everything is interdependently. Also I don't agree that the buffered mode isn't necessary. The buffered mode is obliged to be, and it is preferred way, especially, for the serial port. Since differently, is possible loss the data, related with the limited FIFO sizes (which can be overflowed) and other nuances. :) PS: But it all is offtop... BR, Denis 18.04.2014 21:02, Carlos Duclos ?: Hi. Hi again, Disclaimer. I don't work for Digia and I have never worked for Digia. I did work for Trolltech and Nokia though. I once again fluently look source codes of Qt and I see that the only one I/O class which supports a buffered mode is QTcpSocket (i.e. QAbstractSocket in buffered mode); in which is used the deferred writing for data transfer. Thus, whether can I take such behavior (with deferred writing) as a basis for implementation of I/O in QtSerialPort where only buffered mode is used (as in QTcpSocket) ? Because I don't see other precedents and examples which to take as a basis. What do you think? I think you are starting from the wrong end. The question is not if you should support one mode of operation or the other, that needs to be analyzed case by case. IMHO you should implement both modes of operation and let the user decide which one to use by specifying the right flags at open time. PS: As it is very important part of the project. I think I disagree with that statement. This is not a very important part of the project, it is an implementation detail. Let's talk about serial port support and what is the goal of the project. If I understand correctly what you want to do is to provide a class that can be used for interacting with a serial port and that can be used by other Qt classes seamlessly. If that is not the goal of the project, please explain what is the goal of the project because we might be talking about different things. That being said, a serial port is not something magical, it is something that is used in many situations. Many operating systems provide simple API's to read and write data from and to them. Settings (speed, parity, etc) are usually specified by special calls, such as ioctl. The OS will most likely already provide transparent buffering both for reading and writing, therefore in the strictest sense you shouldn't need to implement buffering at all. However, there are situations when you will want to pretend that you wrote to the serial port, even if the data is still in your buffer. Let's focus on write(2). If you need to operate asynchronously, you need to wait until the OS tells you that is ok to write and possibly only write the amount of data that the OS tells you that is ok to write. In those cases, you might want your data structure to have a write method that puts the data into a buffer, and then request the OS to let you know when it is ok for you to write the data. From the user point of view, the data was written after calling QSerialPort::write(...), even though the data is still somewhere in QSerialPort. Once QSerialPort gets the ok from the OS (probably by waiting until the EventLoop gets the right signal back from the OS), you can start the real transfer of the data to the physical device. Notice that I wrote physical because the OS might do the same thing again and only buffer the data until the hardware says that is ok to send the data. In other situations it might be better for the user if the data is written immediately to the underlying device, even if this might introduce a wait. As explained, most likely the system will buffer the data and usually there are no flush operations on such devices (flush makes sense for file systems but little sense for devices that might freeze the system for ages). If you are using a system where the OS does not provide such abstractions and you need to talk directly to the UART then the picture might be different, but I doubt that
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em sáb 19 abr 2014, às 10:42:27, Denis Shienkov escreveu: But still I didn't receive the concrete response: as to us to be? In a buffer mode is to use the deferred writing or the immediately writing? You choose. If you choose to write immediately in writeData(), justify. Otherwise, follow existing practice. The following classes always buffer: - QProcess - QLocalSocket - QAbstractSocket - QSslSocket Similarly, none of the classes above and neither QNetworkReply actually read from the device in readData(). They only read from the buffer. I haven't looked at what QWebSocket does. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi. My question most likely belongs to the Qt developers from Digia. For example to maintainers of a network subsystem. I see that in QAbstractSocket::write() in a buffered mode is used the deferred data transmission: https://qt.gitorious.org/qt/qtbase/source/454dc332b3856c1726683595575c34281650a469:src/network/socket/qabstractsocket.cpp#L2443 i.e. data are transferred not immediately, but only after the writeNotifier triggering (i.e. after Tx-empty event has been triggered). For me it is interest, why we have this behaviour? What reason in it? e.g., currently we have (for buffered mode): [code] qint64 QAbstractSocket::writeData(const char *data, qint64 size) { ... char *ptr = d-writeBuffer.reserve(size); ... memcpy(ptr, data, size); qint64 written = size; if (d-socketEngine !d-writeBuffer.isEmpty()) d-socketEngine-setWriteNotificationEnabled(true); //// why we do not write whole data from buffer here? // why we skip this, until the notifier was triggering on some next Qt-event loop? return written; } [/code] Why it isn't made for example so ??: {code} qint64 QAbstractSocket::writeData(const char *data, qint64 size) { ... char *ptr = d-writeBuffer.reserve(size); ... memcpy(ptr, data, size); qint64 written = size; if (d-socketEngine !d-writeBuffer.isEmpty()) { // // trying to write whole data from buffer immediately if still we do not have an running streaming // d-flush(); // or d-write or something, i.e. we just write data to device d-socketEngine-setWriteNotificationEnabled(true); } ... return written; } {code} BR, Denis 2014-04-18 0:18 GMT+04:00 Carlos Duclos carlosducl...@yahoo.com: Hi, I'm not sure I understand your question so I'll reply according to what I understood. QIODevice is a generic interface and as such has to provide an interface that works well with different ways of doing things. What seems to confuse you is the possibility of doing buffered communications and non-buffered communications. There is no simple answer to what is correct when it comes to buffered versus non-buffered. There are too many variables involved in making such a decision and therefore QIODevice is flexible enough to work with both approaches. For some type of devices a buffered approach is preferred for some applications while a non-buffered approach might work best in other situations. For example, if your application requires sending chunks of data once a day (let's think of a control device hanging somewhere in a building) and the data is computed before sending it, then a buffered approach might be the right solution. You do your calculation, print what you need to print and once you are done with that the device might empty the buffer and continue. This is a common situation in embedded devices that are connected over slow communication lines, such as RS232 or RS485 (or even 422). If the device is instead connected to a fast communication line and it requires to send data often, then writing it directly might be the right choice. There is no unique way to answer the problem without knowing exactly what you are trying to do. What QIODevice allows you is to implement your own device that works as you need it. If buffering is the right solution to your problem then you use buffering, if not you don't use it. If it is difficult to decide which approach, implement both and let the open method tell you which one to use. The key point is that you can specialize your device as much as you want and the interface will allow it. In the case of a serial port, then there are already several layers of buffering starting at the hardware level all the way to the OS. This allows to write a lot of data but at the cost of introducing delays that might be difficult to control. Regarding your final question about how many bytes you will receive, it is difficult to answer without knowing more details such as what kind of device you were using. If I missed the point and I did not understand your questions, please accept my apologies and ask the question in another way. Cheers! Hi all. I have the question concerning correct treatment of documentation and implementation of I/O methods, e.g. for QtSerialPort. == write == For example, regarding to the QIODevice::write() method. Investigating of Qt5 source codes I see two approaches in classes derived from QIODevice (I talk about the buffered mode): 1) Deferred writing When QIODevice::write () only adds a next portion of data to the internal write buffer. But real data transmission is carried out later, on an next step: on a signal from an notifier (for example from the Tx FIFO event, that signalise about FIFO is empty and can be sent next portion of data from the internal buffer). This
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi. I once again fluently look source codes of Qt and I see that the only one I/O class which supports a buffered mode is QTcpSocket (i.e. QAbstractSocket in buffered mode); in which is used the deferred writing for data transfer. Thus, whether can I take such behavior (with deferred writing) as a basis for implementation of I/O in QtSerialPort where only buffered mode is used (as in QTcpSocket) ? Because I don't see other precedents and examples which to take as a basis. What do you think? PS: As it is very important part of the project. BR, Denis 2014-04-18 14:32 GMT+04:00 Denis Shienkov denis.shien...@gmail.com: Hi. My question most likely belongs to the Qt developers from Digia. For example to maintainers of a network subsystem. I see that in QAbstractSocket::write() in a buffered mode is used the deferred data transmission: https://qt.gitorious.org/qt/qtbase/source/454dc332b3856c1726683595575c34281650a469:src/network/socket/qabstractsocket.cpp#L2443 i.e. data are transferred not immediately, but only after the writeNotifier triggering (i.e. after Tx-empty event has been triggered). For me it is interest, why we have this behaviour? What reason in it? e.g., currently we have (for buffered mode): [code] qint64 QAbstractSocket::writeData(const char *data, qint64 size) { ... char *ptr = d-writeBuffer.reserve(size); ... memcpy(ptr, data, size); qint64 written = size; if (d-socketEngine !d-writeBuffer.isEmpty()) d-socketEngine-setWriteNotificationEnabled(true); //// why we do not write whole data from buffer here? // why we skip this, until the notifier was triggering on some next Qt-event loop? return written; } [/code] Why it isn't made for example so ??: {code} qint64 QAbstractSocket::writeData(const char *data, qint64 size) { ... char *ptr = d-writeBuffer.reserve(size); ... memcpy(ptr, data, size); qint64 written = size; if (d-socketEngine !d-writeBuffer.isEmpty()) { // // trying to write whole data from buffer immediately if still we do not have an running streaming // d-flush(); // or d-write or something, i.e. we just write data to device d-socketEngine-setWriteNotificationEnabled(true); } ... return written; } {code} BR, Denis 2014-04-18 0:18 GMT+04:00 Carlos Duclos carlosducl...@yahoo.com: Hi, I'm not sure I understand your question so I'll reply according to what I understood. QIODevice is a generic interface and as such has to provide an interface that works well with different ways of doing things. What seems to confuse you is the possibility of doing buffered communications and non-buffered communications. There is no simple answer to what is correct when it comes to buffered versus non-buffered. There are too many variables involved in making such a decision and therefore QIODevice is flexible enough to work with both approaches. For some type of devices a buffered approach is preferred for some applications while a non-buffered approach might work best in other situations. For example, if your application requires sending chunks of data once a day (let's think of a control device hanging somewhere in a building) and the data is computed before sending it, then a buffered approach might be the right solution. You do your calculation, print what you need to print and once you are done with that the device might empty the buffer and continue. This is a common situation in embedded devices that are connected over slow communication lines, such as RS232 or RS485 (or even 422). If the device is instead connected to a fast communication line and it requires to send data often, then writing it directly might be the right choice. There is no unique way to answer the problem without knowing exactly what you are trying to do. What QIODevice allows you is to implement your own device that works as you need it. If buffering is the right solution to your problem then you use buffering, if not you don't use it. If it is difficult to decide which approach, implement both and let the open method tell you which one to use. The key point is that you can specialize your device as much as you want and the interface will allow it. In the case of a serial port, then there are already several layers of buffering starting at the hardware level all the way to the OS. This allows to write a lot of data but at the cost of introducing delays that might be difficult to control. Regarding your final question about how many bytes you will receive, it is difficult to answer without knowing more details such as what kind of device you were using. If I missed the point and I did not understand your questions, please accept my apologies and ask the question in another way. Cheers! Hi
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em sex 18 abr 2014, às 18:14:43, Denis Shienkov escreveu: Hi. I once again fluently look source codes of Qt and I see that the only one I/O class which supports a buffered mode is QTcpSocket (i.e. QAbstractSocket in buffered mode); in which is used the deferred writing for data transfer. Thus, whether can I take such behavior (with deferred writing) as a basis for implementation of I/O in QtSerialPort where only buffered mode is used (as in QTcpSocket) ? Because I don't see other precedents and examples which to take as a basis. QProcess is also like that. In both cases, the underlying I/O mechanism cannot take unlimited amounts of data. The OS will only receive a certain number of bytes from the application before saying no more. So the writeData() functions for those two classes must be able to buffer everything that can't be written immediately. Why it doesn't write immediately, I don't know. It was like that when I arrived in 2006. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Em sex 18 abr 2014, às 14:32:49, Denis Shienkov escreveu: My question most likely belongs to the Qt developers from Digia. For example to maintainers of a network subsystem. Note: none of the 3 network maintainers work for Digia. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi. Hi again, Disclaimer. I don't work for Digia and I have never worked for Digia. I did work for Trolltech and Nokia though. I once again fluently look source codes of Qt and I see that the only one I/O class which supports a buffered mode is QTcpSocket (i.e. QAbstractSocket in buffered mode); in which is used the deferred writing for data transfer. Thus, whether can I take such behavior (with deferred writing) as a basis for implementation of I/O in QtSerialPort where only buffered mode is used (as in QTcpSocket) ? Because I don't see other precedents and examples which to take as a basis. What do you think? I think you are starting from the wrong end. The question is not if you should support one mode of operation or the other, that needs to be analyzed case by case. IMHO you should implement both modes of operation and let the user decide which one to use by specifying the right flags at open time. PS: As it is very important part of the project. I think I disagree with that statement. This is not a very important part of the project, it is an implementation detail. Let's talk about serial port support and what is the goal of the project. If I understand correctly what you want to do is to provide a class that can be used for interacting with a serial port and that can be used by other Qt classes seamlessly. If that is not the goal of the project, please explain what is the goal of the project because we might be talking about different things. That being said, a serial port is not something magical, it is something that is used in many situations. Many operating systems provide simple API's to read and write data from and to them. Settings (speed, parity, etc) are usually specified by special calls, such as ioctl. The OS will most likely already provide transparent buffering both for reading and writing, therefore in the strictest sense you shouldn't need to implement buffering at all. However, there are situations when you will want to pretend that you wrote to the serial port, even if the data is still in your buffer. Let's focus on write(2). If you need to operate asynchronously, you need to wait until the OS tells you that is ok to write and possibly only write the amount of data that the OS tells you that is ok to write. In those cases, you might want your data structure to have a write method that puts the data into a buffer, and then request the OS to let you know when it is ok for you to write the data. From the user point of view, the data was written after calling QSerialPort::write(...), even though the data is still somewhere in QSerialPort. Once QSerialPort gets the ok from the OS (probably by waiting until the EventLoop gets the right signal back from the OS), you can start the real transfer of the data to the physical device. Notice that I wrote physical because the OS might do the same thing again and only buffer the data until the hardware says that is ok to send the data. In other situations it might be better for the user if the data is written immediately to the underlying device, even if this might introduce a wait. As explained, most likely the system will buffer the data and usually there are no flush operations on such devices (flush makes sense for file systems but little sense for devices that might freeze the system for ages). If you are using a system where the OS does not provide such abstractions and you need to talk directly to the UART then the picture might be different, but I doubt that you will be using Qt if that was the case. Cheers!___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [QIODevice]How to correctly treat/understand of the documentation?
Hi, I'm not sure I understand your question so I'll reply according to what I understood. QIODevice is a generic interface and as such has to provide an interface that works well with different ways of doing things. What seems to confuse you is the possibility of doing buffered communications and non-buffered communications. There is no simple answer to what is correct when it comes to buffered versus non-buffered. There are too many variables involved in making such a decision and therefore QIODevice is flexible enough to work with both approaches. For some type of devices a buffered approach is preferred for some applications while a non-buffered approach might work best in other situations. For example, if your application requires sending chunks of data once a day (let's think of a control device hanging somewhere in a building) and the data is computed before sending it, then a buffered approach might be the right solution. You do your calculation, print what you need to print and once you are done with that the device might empty the buffer and continue. This is a common situation in embedded devices that are connected over slow communication lines, such as RS232 or RS485 (or even 422). If the device is instead connected to a fast communication line and it requires to send data often, then writing it directly might be the right choice. There is no unique way to answer the problem without knowing exactly what you are trying to do. What QIODevice allows you is to implement your own device that works as you need it. If buffering is the right solution to your problem then you use buffering, if not you don't use it. If it is difficult to decide which approach, implement both and let the open method tell you which one to use. The key point is that you can specialize your device as much as you want and the interface will allow it. In the case of a serial port, then there are already several layers of buffering starting at the hardware level all the way to the OS. This allows to write a lot of data but at the cost of introducing delays that might be difficult to control. Regarding your final question about how many bytes you will receive, it is difficult to answer without knowing more details such as what kind of device you were using. If I missed the point and I did not understand your questions, please accept my apologies and ask the question in another way. Cheers! Hi all. I have the question concerning correct treatment of documentation and implementation of I/O methods, e.g. for QtSerialPort. == write == For example, regarding to the QIODevice::write() method. Investigating of Qt5 source codes I see two approaches in classes derived from QIODevice (I talk about the buffered mode): 1) Deferred writing When QIODevice::write () only adds a next portion of data to the internal write buffer. But real data transmission is carried out later, on an next step: on a signal from an notifier (for example from the Tx FIFO event, that signalise about FIFO is empty and can be sent next portion of data from the internal buffer). This behavior is implemented, for example in the QAbstractSocket for a buffered mode. 2) Directly writing This approach when the QIODevice::write() transfers data at once to the device, directly. I.e. in my head there is a confusion. How it is necessary to do for the buffered mode more correctly? For me, more pleasant that is the first method... But, if I am not right (i.e. when need to use directly writing to minimize time between packets), then what reasons in TCP socket the first deferred method is used? == flush == What expected behavior for the QIODevice::flush() method and for the bytesWritten(qint64) signal? For example two scenarios: 1) Without flush() MyClass::foo() { p.write('a'); p.write('b'); } MyClass::bar() { p.write('c'); p.write('d'); } when, the bar() method were called after foo() (with some delay), but when not all data (a and b) was written (e.g. was in time written only a). then I expected to receive two: bytesWrittenSignal(2 byte) + bytesWrittenSignal(2 byte) 2) With flush() MyClass::foo() { p.write('a'); p.write('b'); } MyClass::bar() { p.write('c'); p.write('d'); p.flush(); } when, the bar() method were called after foo() (with some delay), but when not all data (a and b) was written (e.g. was in time written only a). then I expected to receive one bytesWrittenSignal(4 byte) Whether correctly I understand?nd for expected behavior? Best regards, Denis El Jueves, 17 de abril, 2014 5:15 P.M., development-requ...@qt-project.org development-requ...@qt-project.org escribió: Send Development mailing list submissions to development@qt-project.org To subscribe or unsubscribe via the World Wide Web, visit http://lists.qt-project.org/mailman/listinfo/development or, via email, send a message with subject or body 'help' to development-requ...@qt-project.org You