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

Denis Shienkov denis.shienkov at gmail.com
Fri Apr 18 12:32:49 CEST 2014


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 <carlosduclosv at 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 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
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20140418/08f7a855/attachment.html>


More information about the Development mailing list