揭秘 propertyToWrappedProperty()->insert(varProp, internProp)

本文详细介绍了Qt框架中Q_GLOBAL_STATIC宏的使用方法、注意事项及其实现原理,包括静态全局对象的创建、生命周期管理、线程安全性和构造函数的调用方式。同时,通过剖析宏的原始定义和内部类实现,揭示了其如何确保全局对象的高效初始化、线程安全以及在程序结束时的正确销毁。此外,还阐述了Q_GLOBAL_STATIC宏与其他Qt组件如QMutex的协同作用,特别强调了其在创建线程安全单例对象时的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、看宏定义

typedef QMap<const QtProperty *, QtProperty *> PropertyMap;
Q_GLOBAL_STATIC(PropertyMap, propertyToWrappedProperty)


2、Q_GLOBAL_STATIC 。使用Q_GLOBAL_STATIC宏来创建静态全局对象,例如:

Q_STATIC_GLOBAL(QString, s)
      void foo()
      {
          s()->append("moo");
      }


有2个注意点:1 该函数虽然大量在QT应用,但是为内部函数,不保证未来还能用; 并且该宏在各个版本中经常有细节的变化。2 在 QT 标准编程惯例 中,说,在局部范围内使用静态对象是没有问题的,当进入这个局部时,构造函数会首次被运行。但是这段代码是不可重入的。 但是在 QT 开发网 中,有回复说是 Q_GLOBAL_STATIC is re-entrant and thread safe. Note however that the constructor of your object might be called several time (from different threads (but the extra objects are destroyed quickly) 比较困惑。

看看我千辛万苦搜到的一个注释  重复写在这里

Creating C++ classes in global space is generally a bad idea, because the order of construction is undefined. On top of that, constructors require execution, thus slowing down your program startup time. Enter Q_GLOBAL_STATIC. It works like this:

Q_GLOBAL_STATIC(Foo, get_foo)

Write this in your global space, and it will define a function called get_foo() that essentially does “new Foo” (if it has not done so already) and returns it. Now, instead of using the object directly, you use the function. This puts you in control of when your global objects are created, and gives you lazy-loading to boot. An atomic integer operation is used for thread-safe construction. In addition, a static template class “wrapper” is defined for your type, so that your object will be properly destructed on exit, just like a normal global type. Granted, this is a slight bit of overhead, but probably less than any object you’d use it with. There’s even Q_GLOBAL_STATIC_WITH_ARGS().

You probably shouldn’t be using globals anyway, but sometimes you need them. Q_GLOBAL_STATIC seems particularly useful with QMutex, the bare-minimum to get you off the ground for creating thread-safe singletons.

 这个是一个很好的介绍内存顺序的小文章,有这个宏的一点解释。

3、Q_GLOBAL_STATIC 的原始定义

#define Q_GLOBAL_STATIC_INIT(TYPE, NAME)                              \
    static QGlobalStatic<TYPE > this_##NAME = { Q_BASIC_ATOMIC_INITIALIZER(0), false }

#define Q_GLOBAL_STATIC(TYPE, NAME)                                     \
    Q_GLOBAL_STATIC_INIT(TYPE, NAME);                                   \
    static TYPE *NAME()                                                 \
    {                                                                   \
        if (!this_##NAME.pointer && !this_##NAME.destroyed) {           \
            TYPE *x = new TYPE;                                         \
            if (!this_##NAME.pointer.testAndSetOrdered(0, x))           \
                delete x;                                               \
            else                                                        \
                static QGlobalStaticDeleter<TYPE > cleanup(this_##NAME); \
        }                                                               \
        return this_##NAME.pointer;                                     \
    }


则 1 展开后得到。Q_GLOBAL_STATIC  这个宏我看以前的版本其静态成员是在函数内部定义的,现在提到外部何意? 是为了更早地初始化该静态成员??

testAndSetOrdered 是线程安全地测试并赋值,具体可看QT文档。如果设置失败,即有可能该值已经赋值过了,则删除 x ; 否者,建立一个全局静态对象,保证在程序退出时删除该静态变量。QGlobalStaticDeleter见后面的定义。

static QGlobalStatic<PropertyMap > this_propertyToWrappedProperty= { Q_BASIC_ATOMIC_INITIALIZER(0), false };

static PropertyMap *propertyToWrappedProperty()
{                                                                   
	if (!this_propertyToWrappedProperty.pointer && !this_propertyToWrappedProperty.destroyed) {           
		PropertyMap *x = new PropertyMap;                                         
		if (!this_propertyToWrappedProperty.pointer.testAndSetOrdered(0, x))           
			delete x;                                              
		else                                                        
			static QGlobalStaticDeleter<PropertyMap > cleanup(this_propertyToWrappedProperty); // cleanup 干嘛用的??
	}                                                               
	return this_propertyToWrappedProperty.pointer;                               
}


4、继续剥皮QGlobalStatic。

template <typename T>
class QGlobalStatic
{
public:
    QBasicAtomicPointer<T> pointer;
    bool destroyed;
};


5、剥皮QBasicAtomicPointer,暂译为“基本原子指针”。为了清楚,去掉了一些条件编译,这里是 XP VC。 看到就是一些 volatile 定义的变量,并提供了一些基本方法。

template <typename T>
class QBasicAtomicPointer
{
public:
    union {
        T * volatile _q_value;
        long volatile _q_value_integral;
    };

    // Non-atomic API
    inline bool operator==(T *value) const
    {
        return _q_value == value;
    }

    inline bool operator!=(T *value) const
    {
        return !operator==(value);
    }

    inline bool operator!() const
    {
        return operator==(0);
    }

    inline operator T *() const
    {
        return _q_value;
    }

    inline T *operator->() const
    {
        return _q_value;
    }

    inline QBasicAtomicPointer<T> &operator=(T *value)
    {
        _q_value = value;
        return *this;
    }

    // Atomic API, implemented in qatomic_XXX.h

    static bool isTestAndSetNative();
    static bool isTestAndSetWaitFree();

    bool testAndSetRelaxed(T *expectedValue, T *newValue);
    bool testAndSetAcquire(T *expectedValue, T *newValue);
    bool testAndSetRelease(T *expectedValue, T *newValue);
    bool testAndSetOrdered(T *expectedValue, T *newValue);

    static bool isFetchAndStoreNative();
    static bool isFetchAndStoreWaitFree();

    T *fetchAndStoreRelaxed(T *newValue);
    T *fetchAndStoreAcquire(T *newValue);
    T *fetchAndStoreRelease(T *newValue);
    T *fetchAndStoreOrdered(T *newValue);

    static bool isFetchAndAddNative();
    static bool isFetchAndAddWaitFree();

    T *fetchAndAddRelaxed(qptrdiff valueToAdd);
    T *fetchAndAddAcquire(qptrdiff valueToAdd);
    T *fetchAndAddRelease(qptrdiff valueToAdd);
    T *fetchAndAddOrdered(qptrdiff valueToAdd);
};

 

6、剥皮 QGlobalStaticDeleter。看注释吧。 执行时间应该是在程序退出之时才执行。

// Created as a function-local static to delete a QGlobalStatic<T>
template <typename T>
class QGlobalStaticDeleter
{
public:
    QGlobalStatic<T> &globalStatic;
    QGlobalStaticDeleter(QGlobalStatic<T> &_globalStatic)
        : globalStatic(_globalStatic)
    { }

    inline ~QGlobalStaticDeleter()
    {
        delete globalStatic.pointer;
        globalStatic.pointer = 0;
        globalStatic.destroyed = true;
    }
};



 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值