[Interest] QMap and thread-safe.

Thiago Macieira thiago.macieira at intel.com
Wed Jul 24 05:14:49 CEST 2013


On terça-feira, 23 de julho de 2013 22:20:48, william.crocker at analog.com 
wrote:
> > If you want to be 100% certain, I suggest you do your own simple map
> > implementation. It's easy enough to do, if you don't have a huge set of
> > requirements. And you can probably use the QMap hashing, I'm pretty sure
> > that is thread safe.
> > 
> > Whether you want to go to this or take the chance probably depends on
> > how critical this code is.
> 
> Thanks. More thoughts...
> 
> Classes like QString and QMap were designed (using implicit sharing) to
> provide for thread-safe, high-speed pass by value. So, in the following,

Remember the definition of "reentrant": it's ok to call this method from 
multiple threads simultaneously, provided they operate on different objects.

The fact that the internals are implicitly shared is irrelevant. It's 
something that the class needs to deal with, and it needs to provide a 
behaviour for you as if it didn't share anything.

> is it true that AAA is not guaranteed to work, but BBB is?
> 
> bool
> MyContains( const QMap<QString,QString> &map, const QString &str ) {
>      return map.contains(str);
> }
> 
> QMap<QString,QString> GlobalMap;
> 
> bool
> Func( const QString &str ) {
> 
>        // AAA: This might not work from an MT context???
>      return GlobalMap.contains(str);
> 
>        // BBB: But, this always will???
>      return MyContains(GlobalMap,str);
> }

That makes no difference. The compiler will inline the MyContains function and 
you get the exact same call sequence in both (down to the very same byte in 
the assembly, actually).

What Peppe and Bo meant to say is that your function Func above, using either 
AAA or BBB, is not documented to be thread-safe. It is thread-safe with the 
current implementation[*] and we don't plan on breaking that, but it's not 
*documented* to be.

What *is* documented is the following:

struct ThreadContext: QThread
{
    QString value;
    QMap<QString, QString> map;
    bool contains(const QString &str)
    { return map.contains(str); }

    void run() { contains(value); }
};

If you start two ThreadContext threads, each of them operates on two 
independent QString and QMap variables. The above is the definition of 
"reentrant", as per Qt's documentation.


[*] there's one exception: one method in QString that is const and is not 
thread-safe. See if you can tell why:

const ushort *QString::utf16() const
{
    if (IS_RAW_DATA(d)) {
        // ensure '\0'-termination for ::fromRawData strings
        const_cast<QString*>(this)->reallocData(uint(d->size) + 1u);
    }
    return d->data();
}
-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20130723/cb5b4495/attachment.sig>


More information about the Interest mailing list