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;
}
};