Hello

Moving the discussion from the series of patches I've begun on Gerrit to the
ML.

tl;dr: all I wanted was to add the prepend optimisation to QVector so I could
work on QList. Then João told me of a request by Tor Arne about letting
QString have a "notify of destruction" function. So I changed the internals of
QArrayData again.

Current QArrayData is:

struct Q_CORE_EXPORT QArrayData
{
    QtPrivate::RefCount ref;
    int size;
    uint alloc : 31;
    uint capacityReserved : 1;

    qptrdiff offset; // in bytes from beginning of header

    [ member functions ]
};

Size is 3*4 + maybe padding + pointer size = 16 bytes or 24 bytes

After my changes, it is:

struct Q_CORE_EXPORT QArrayData
{
    QtPrivate::RefCount ref;
    uint flags;
    int size;       // ### move to the main class body?
    // -- 4 bytes padding here on 64-bit systems --
    qptrdiff offset; // in bytes from beginning of header
    // size is 16 / 24 bytes
};
struct QArrayAllocatedData : public QArrayData
{
    uint alloc;
    // 4 bytes tail padding on 64-bit systems
    // size is 20 / 32 bytes
};

struct QArrayForeignData : public QArrayData
{
    void *token;
    void (*notifyFunction)(void *);
    // size is 24 / 40 bytes
};

The changes are:
 - instead of a single bit of flags, there's a full integer now (32 bits),
which allow us to to more things.

 - I've reserved 3 of those bits to indicate the type of array: raw data (like
QStringLiteral and fromRawData), heap-allocated data, foreign data.

 - foreign data is like fromRawData: it comes from somewhere else, we don't
manage its memory and it's immutable. The difference is that we'll call a
notify function (see above) when our refcount drops to zero. This allows, for
example, to use QString on data managed by WTF::String or UTF-16 data stored
in an mmap'ed page.

 - the "alloc" member is moved from the standard data to the allocated data
(it makes sense). This member should only ever be accessed in non-const
functions (more or less, there are exceptions), usually after those functions
have decided that they need to allocate or reallocate memory.

 - as a drawback, the header overhead in memory allocation increases 4 bytes
on 32-bit systems and 8 bytes on 64-bit ones (due to the presence of tail
padding). It's possible to store data in that tail padding, though, but I
don't want to .

 - in fact, I was thinking of changing the size and alloc members to size_t,
so this header could be used on a container supporting larger memory sizes, if
we wanted to, in the future.

 - André requested that the size member be moved away from the header into the
main class body itself. I haven't done that yet and I'm not sure I should. It
would be major surgery for something that we haven't proven yet. And I don't
think we have time to prove it. But it would decrease the size of the header
by 8 bytes on 64-bit systems.

 - since we stored the type of the data, we know when we allocated it. Since
we know that and we know the size of the header, the "offset" member becomes
the prepend optimisation: we know how much buffer we have between the end of
the header and the beginning of the data.

Besides all that, there are a bunch of small changes. Before we discuss the
minor changes and implementation details (whether we need one or two option
enums, for example), I'd like to know if anyone has more ideas relating to the
headers themselves.

--
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center
     Intel Sweden AB - Registration Number: 556189-6027
     Knarrarnäsgatan 15, 164 40 Kista, Stockholm, Sweden

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development

Reply via email to