Can Q_GLOBAL_STATIC replace KStaticDelete ?

Matthias Kretz kretz at kde.org
Thu Jan 18 23:48:02 GMT 2007


On Thursday 18 January 2007 23:45, Thiago Macieira wrote:
> Matthias Kretz wrote:
> >The problem is that if thread 1 inits this_##NAME and then executes the
> > code in the macro (creating a new object and returning it) while thread
> > 2 does the same, the internal flag that the local static has been
> > initialized might still be unset so that thread 2 creates a second
> > QGlobalStatic object which tells the macro that the object has not been
> > created yet.
>
> That's what I said :-)

I think we're misunderstanding each other right now. Let's try and pin down 
the misunderstanding...

You're saying that Q_GLOBAL_STATIC is threadsafe because of 
QBasicAtomicPointer, which makes the assignment of the object pointer atomic. 
And I understood that you were saying that Q_GLOBAL_STATIC does not need 
threadsafe local statics, right?

I said that Q_GLOBAL_STATIC is not threadsafe if initialization of local 
statics is not atomic. Because if two QGlobalStatic objects are created (one 
in each thread, a really rare race condition, but it can happen as my 
testcase shows) QBasicAtomicPointer can't help anymore.

> And that's where QBasicAtomicPointer comes in (not QAtomicPointer because
> that isn't POD). It allows us to atomically set the pointer without the
> need for a guard variable.

How about using the code below for doing what Q_GLOBAL_STATIC is supposed to 
do (it could use a little more logic to return 0 after destruction, but 
that's not necessary here). The idea is to use QBasicAtomicPointer to guard 
against concurrent initialization of the local static:

-- 
________________________________________________________
Matthias Kretz (Germany)                            <><
http://Vir.homelinux.org/
MatthiasKretz at gmx.net, kretz at kde.org,
Matthias.Kretz at urz.uni-heidelberg.de
-------------- next part --------------
template<typename T>
class KCleanUpGlobalStatic
{
    public:
        T *pointer;

        inline ~KCleanUpGlobalStatic()
        {
            delete pointer;
            pointer = 0;
        }
};

#define K_GLOBAL_STATIC(TYPE, NAME)                                              \
static QBasicAtomicPointer<TYPE > _k_static_##NAME = Q_ATOMIC_INIT(0);           \
TYPE *NAME()                                                                     \
{                                                                                \
    if (!_k_static_##NAME) {                                                     \
        TYPE *x = new TYPE;                                                      \
        if (!_k_static_##NAME.testAndSet(0, x)) {                                \
            delete x;                                                            \
        } else {                                                                 \
            static KCleanUpGlobalStatic<A> cleanUpObject = { _k_static_##NAME }; \
        }                                                                        \
    }                                                                            \
    return _k_static_##NAME;                                                     \
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20070119/1bdbd834/attachment.sig>


More information about the kde-core-devel mailing list