Revision control
++ // Copyright (C) 2021 Intel Corporation.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \macro Q_GLOBAL_STATIC(Type, variableName, ...)
++ \since 5.1
++ \relates QGlobalStatic
++
++ Creates a global and static object of type \l QGlobalStatic, named \a
++ variableName. It behaves as a pointer to \a Type. The object created by
++ Q_GLOBAL_STATIC initializes itself on the first use, which means that it
++ will not increase the application or the library's load time. Additionally,
++ the object is initialized in a thread-safe manner on all platforms.
++
++ Since Qt 6.3, this macro admits variadic arguments, which are used to
++ initialize the object, thus making the need for \l
++ Q_GLOBAL_STATIC_WITH_ARGS unnecessary. Please note the arguments do not
++ require an extra set of parentheses, unlike the older macro.
++
++ The typical use of this macro is as follows, in a global context (that is,
++ not inside any function or class body):
++
++ \code
++ Q_GLOBAL_STATIC(MyType, myGlobal)
++ \endcode
++
++ This macro is intended to replace global static objects that are not POD
++ (Plain Old Data, or in C++11 terms, not made of a trivial type), hence the
++ name. For example, the following C++ code creates a global static:
++
++ \code
++ static MyType myGlobal;
++ \endcode
++
++ Compared to Q_GLOBAL_STATIC, and assuming that \c MyType is a class or
++ struct that has a constructor, a destructor, or is otherwise non-POD, the
++ latter has the following drawbacks:
++
++ \list
++ \li it requires load-time initialization of \c myGlobal (that is, the
++ default constructor for \c MyType is called when the library or
++ application is loaded);
++
++ \li the object will be initialized even if it is never used;
++
++ \li the order of initialization and destruction among different
++ translation units is not determined, leading to possible uses,
++ before initialization or after destruction, by the constructors or
++ destructors of other global variables.
++ \endlist
++
++ The Q_GLOBAL_STATIC macro solves all of these problems by guaranteeing
++ thread-safe initialization on first use and allowing the user to query for
++ whether the type has already been destroyed, to avoid the
++ use-after-destruction problem (see \l QGlobalStatic::isDestroyed()).
++
++ \section1 Constructor and Destructor
++
++ For Q_GLOBAL_STATIC, when only given a type and variable name, its \c Type
++ must be publicly default-constructible and publicly destructible.
++ Otherwise, \c Type must have a public constructor that accepts the remaining
++ arguments to the macro. For Q_GLOBAL_STATIC_WITH_ARGS(), there must be a
++ public constructor that accepts the macro's third argument as its list of
++ parameters.
++
++ It is not possible to use Q_GLOBAL_STATIC with a \a Type whose relevant
++ constructor or destructor is protected or private. If the type in question
++ declares those members protected, it is possible to overcome the issue by
++ deriving from the type and creating a public constructor and destructor. If
++ the type declares them private, a friend declaration is necessary before
++ deriving.
++
++ For example, the following is enough to create \c MyType based on a
++ previously-defined \c MyOtherType which has a protected default constructor
++ and/or a protected destructor (or declares them private, but also declares
++ \c MyType as a friend).
++
++ \code
++ class MyType : public MyOtherType { };
++ Q_GLOBAL_STATIC(MyType, myGlobal)
++ \endcode
++
++ No body for \c MyType is required since the destructor is an implicit member
++ and so is the default constructor if no other constructors are defined. For
++ use with arguments after \a Type and \a variableName, or with
++ Q_GLOBAL_STATIC_WITH_ARGS(), however, a suitable constructor body is
++ necessary:
++
++ \code
++ class MyType : public MyOtherType
++ {
++ public:
++ MyType(int i) : MyOtherType(i) {}
++ };
++ Q_GLOBAL_STATIC(MyType, myGlobal, 42)
++ \endcode
++
++ Alternatively (since C++11 introduced inheriting constructors), one could
++ write:
++
++ \code
++ class MyType : public MyOtherType
++ {
++ public:
++ using MyOtherType::MyOtherType;
++ };
++ Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42))
++ \endcode
++
++ \section1 Placement
++
++ The Q_GLOBAL_STATIC macro creates a type, and a variable of that type that
++ is necessarily static, at the global scope. It is not possible to place the
++ Q_GLOBAL_STATIC macro inside a function or the body of a class (doing so
++ will result in compilation errors).
++
++ More importantly, this macro should be placed in source files, never in
++ headers. Since the resulting object has static linkage, if the macro is
++ placed in a header and included by multiple source files, the object will be
++ defined multiple times and will not cause linking errors. Instead, each
++ translation unit will refer to a different object, which could lead to
++ subtle and hard-to-track errors.
++
++ \section1 Non-recommended uses
++
++ Note that the macro is not recommended for use with types that are POD or
++ that have C++11 constexpr constructors (trivially constructible and
++ destructible). For those types, it is still recommended to use regular
++ static, whether global or function-local.
++
++ This macro will work, but it will add unnecessary overhead.
++
++ \section1 Reentrancy, Thread-safety, Deadlocks, and Exception-safety on Construction
++
++ The Q_GLOBAL_STATIC macro creates an object that initializes itself on
++ first use in a thread-safe manner: if multiple threads attempt to
++ initialize the object at the same time, only one thread will proceed to
++ initialize, while all other threads wait for completion.
++
++ If the initialization process throws an exception, the initialization is
++ deemed not complete and will be attempted again when control reaches any
++ use of the object. If there are any threads waiting for initialization, one
++ of them will be woken up to attempt to initialize.
++
++ The macro makes no guarantee about reentrancy from the same thread. If the
++ global static object is accessed directly or indirectly from inside its own
++ constructor, a deadlock will surely happen.
++
++ In addition, if two Q_GLOBAL_STATIC objects are being initialized on two
++ different threads and each one's initialization sequence accesses the
++ other, a deadlock might happen. For that reason, it is recommended to keep
++ global static constructors simple or, failing that, to ensure that there's
++ no cross-dependency of uses of global static during construction.
++
++ \section1 Destruction
++
++ If the object is never used during the lifetime of the program, aside from
++ the QGlobalStatic::exists() and QGlobalStatic::isDestroyed() functions, the
++ contents of type \a Type will not be created and there will not be any
++ exit-time operation.
++
++ If the object is created, it will be destroyed at exit-time, similar to the
++ C \c atexit() function. On most systems, in fact, the destructor will also
++ be called if the library or plugin is unloaded from memory before exit.
++
++ Since the destruction is meant to happen at program exit, no thread-safety
++ is provided. This includes the case of plugin or library unload. In
++ addition, since destructors are not supposed to throw exceptions, no
++ exception safety is provided either.
++
++ However, reentrancy is permitted: during destruction, it is possible to
++ access the global static object and the pointer returned will be the same
++ as it was before destruction began. After the destruction has completed,
++ accessing the global static object is not permitted, except as noted in the
++ \l QGlobalStatic API.
++
++ \omit
++ \section1 Compatibility with Qt 4 and Qt 5.0
++
++ This macro, in its current behavior, was introduced in Qt 5.1. Prior to
++ that version, Qt had another macro with the same name that was private API.
++ This section is not meant to document how to use Q_GLOBAL_STATIC in those
++ versions, but instead to serve as a porting guide for Qt code that used
++ those macros.
++
++ The Qt 4 Q_GLOBAL_STATIC macro differed in behavior in the following ways:
++
++ \list
++ \li the object created was not of type \l QGlobalStatic, but instead it
++ was a function that returned a pointer to \a Type; that means the \l
++ QGlobalStatic API was not present;
++
++ \li the initialization was thread-safe, but not guaranteed to be unique:
++ instead, if N threads tried to initialize the object at the same
++ time, N objects would be created on the heap and N-1 would be
++ destroyed;
++
++ \li the object was always created on the heap.
++ \endlist
++
++ \section1 Implementation Details
++
++ Q_GLOBAL_STATIC is implemented by creating a type called \c Q_QGS_NAME where
++ \c NAME is the \a variableName the user passed to the macro, inside an
++ unnamed namespace, and a \c static variable of \l QGlobalStatic type, named
++ \a variableName. The use of unnamed namespaces forces the compiler to emit
++ non-exported symbols, often local to the translation unit, and this
++ propagates to the \l QGlobalStatic template instantiation that uses such
++ types. Additionally, because the type is used only for one variable, there's
++ effectively no difference between static and non-static data members.
++
++ The "QGS" type is a \c struct containing a \c typedef to \a Type and a
++ static member function that receives a pointer to storage suitable to hold
++ an instance of \a Type. It will initialize the storage using a placement \c
++ new and the variadic arguments.
++
++ The majority of the work is done by the public \l QGlobalStatic class and
++ the private \c QtGlobalStatic::Holder class. The \c Holder union has a
++ single non-static member of type \a Type, but because this is a union, its
++ construction and destruction are explicitly controlled in the Holder's
++ constructor and destructor. The constructor calls the "QGS" type's static
++ member function with a pointer to this member so it can be initialized
++ and the destructor calls the type's destructor. The \c{Holder} type is
++ therefore neither trivially constructible nor trivially destructible. It is
++ used as a function-local \c static so its initialization is thread-safe due
++ to C++11's requirement that such variables be thread-safely initialized.
++
++ Additionally, both the constructor and destructor modify a guard variable
++ after construction and before destruction, respectively. The guard variable
++ is implemented as a \c {static inline} member instead of a non-static
++ member so the compiler and linker are free to place this variable in memory
++ far from the actual object. This way, if we wanted to, we could mark it
++ aligned-to-cacheline in the future to prevent false sharing.
++
++ The guard variable can assume the following values:
++
++ \list
++ \li -2: object was once initialized but has been destroyed already;
++ \li -1: object was initialized and is still valid;
++ \li 0: object was not initialized yet;
++ \li +1: object is being initialized and any threads encountering this
++ value must wait for completion (not used in the current
++ implementation).
++ \endlist
++
++ Collectively, all positive values indicate that the initialization is
++ progressing and must be waited on, whereas all negative values indicate
++ that the initialization has terminated and must not be attempted again.
++ Positive values are not used in the current implementation, but were in
++ earlier versions. They could be used again in the future.
++
++ The QGlobalStatic::exists() and QGlobalStatic::isDestroyed() functions
++ operate solely on the guard variable: the former returns \c true if the guard
++ is -1, the latter returns \c true if it is -2.
++
++ \endomit
++
++ \sa Q_APPLICATION_STATIC(), QGlobalStatic
++ */
++
++ /*!
++ \macro Q_GLOBAL_STATIC_WITH_ARGS(Type, variableName, Arguments)
++ \since 5.1
++ \obsolete [6.4]
++ \relates QGlobalStatic
++
++ Creates a global and static object of type \l QGlobalStatic, of name \a
++ variableName, initialized by the arguments \a Arguments and that behaves as
++ a pointer to \a Type. The object created by Q_GLOBAL_STATIC_WITH_ARGS
++ initializes itself on the first use, which means that it will not increase
++ the application or the library's load time. Additionally, the object is
++ initialized in a thread-safe manner on all platforms.
++
++ The typical use of this macro is as follows, in a global context (that is,
++ not inside any function or class body):
++
++ \code
++ Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42, "Hello", "World"))
++ \endcode
++
++ The \a Arguments macro parameter must always be enclosed in parentheses or,
++ if C++11 uniform initialization is allowed, braces. The above call is
++ equivalent to
++
++ \code
++ Q_GLOBAL_STATIC(MyType, myGlobal, 42, "Hello", "World")
++ \endcode
++
++ Aside from needing the supplied arguments enclosed, this macro behaves
++ identically to Q_GLOBAL_STATIC(). Please see that macro's documentation for
++ more information.
++
++ \sa Q_GLOBAL_STATIC(), QGlobalStatic
++ */
++
++ /*!
++ \class QGlobalStatic
++ \threadsafe
++ \inmodule QtCore
++ \since 5.1
++ \brief The QGlobalStatic class is used to implement a global static object.
++
++ QGlobalStatic\<Holder\> is a template class where \a Holder is an internal
++ type generated by the Q_GLOBAL_STATIC() macro. The user-visible type of the
++ global static object is accessible via the \l{QGlobalStatic::Type}{Type}
++ typedef.
++
++ The QGlobalStatic class is the front-end API exported when \l
++ Q_GLOBAL_STATIC() is used. See the documentation of the macro for a
++ discussion of its requirements and when to use it.
++
++ Normally, you will never use this class directly, but instead you will use
++ the Q_GLOBAL_STATIC() macro, as follows:
++
++ \code
++ Q_GLOBAL_STATIC(MyType, myGlobal)
++ \endcode
++
++ The above example creates an object of type QGlobalStatic called \c
++ myGlobal. After the above declaration, the \c myGlobal object may be used as
++ if it were a pointer to an object of type \c MyType, guaranteed to be
++ initialized exactly once. In addition to the use as a pointer, the object
++ offers two methods to determine the current status of the global: exists()
++ and isDestroyed().
++
++ \sa Q_GLOBAL_STATIC()
++ */
++
++ /*!
++ \typedef QGlobalStatic::Type
++
++ This type is equivalent to the \c Type parameter passed to the
++ Q_GLOBAL_STATIC() or Q_GLOBAL_STATIC_WITH_ARGS() macros. It is used in the
++ return types of some functions.
++ */
++
++ /*!
++ \fn template <typename Holder> bool QGlobalStatic<Holder>::isDestroyed() const
++
++ This function returns \c true if the global static object has already
++ completed destruction (that is, if the destructor for the type has already
++ returned). In particular, note that this function returns \c false if the
++ destruction is still in progress.
++
++ Once this function has returned true once, it will never return
++ false again until either the program is restarted or the plugin or library
++ containing the global static is unloaded and reloaded.
++
++ This function is safe to call at any point in the program execution: it
++ cannot fail and cannot cause a deadlock. Additionally, it will not cause
++ the contents to be created if they have not yet been created.
++
++ This function is useful in code that may be executed at program shutdown,
++ to determine whether the contents may still be accessed or not.
++
++ \omit
++ Due to the non-atomic nature of destruction, it's possible that
++ QGlobalStatic::isDestroyed might return false for a short time after the
++ destructor has finished. However, since the destructor is only run in an
++ environment where concurrent multithreaded access is impossible, no one can
++ see that state. (omitted because it's useless information)
++ \endomit
++
++ \sa exists()
++ */
++
++ /*!
++ \fn template <typename Holder> bool QGlobalStatic<Holder>::exists() const
++
++ This function returns \c true if the global static object has already
++ completed initialization (that is, if the constructor for the type has
++ already returned) and has not yet completed destruction. In particular, note
++ that this function returns \c false if the initialization is still in
++ progress.
++
++ Once this function has returned true once, it will never return false again
++ until the global static object is destroyed. The latter happens on program
++ exit or when the plugin or library containing the global static is unloaded.
++
++ This function is safe to call at any point in the program execution: it
++ cannot fail and cannot cause a deadlock. Additionally, it will not cause
++ the contents to be created if they have not yet been created.
++
++ This function is useful if one can determine the initial conditions of the
++ global static object and would prefer to avoid a possibly expensive
++ construction operation.
++
++ For example, in the following code sample, this function is used to
++ short-circuit the creation of the global static called \c globalState and
++ returns a default value:
++
++ \code
++ Q_GLOBAL_STATIC(MyType, globalState)
++ QString someState()
++ {
++ if (globalState.exists())
++ return globalState->someState;
++ return QString();
++ }
++ \endcode
++
++ \b{Thread-safety notice:} this function is thread-safe in the sense that it
++ may be called from any thread at any time and will always return a valid
++ reply. But due to the non-atomic nature of construction, this function may
++ return false for a short time after the construction has completed.
++
++ \b{Memory ordering notice:} this function does not impose any memory
++ ordering guarantees. That is instead provided by the accessor functions
++ that return the pointer or reference to the contents. If you bypass the
++ accessor functions and attempt to access some global state set by the
++ constructor, be sure to use the correct memory ordering semantics provided
++ by \l QAtomicInt or \l QAtomicPointer.
++
++ \sa isDestroyed()
++ */
++
++ /*!
++ \keyword qglobalstatic-operator-type-ptr
++ \fn template <typename Holder> QGlobalStatic<Holder>::operator Type*()
++
++ This function returns the address of the contents of this global static. If
++ the contents have not yet been created, they will be created thread-safely
++ by this function. If the contents have already been destroyed, this
++ function will return a null pointer.
++
++ This function can be used, for example, to store the pointer to the
++ contents of the global static in a local variable, thus avoiding multiple
++ calls to the function. The implementation of Q_GLOBAL_STATIC() is quite
++ efficient already, but in performance-critical sections it might be useful
++ to help the compiler a little. For example:
++
++ \code
++ Q_GLOBAL_STATIC(MyType, globalState)
++ QString someState()
++ {
++ if (globalState::isDestroyed())
++ return QString();
++ MyType *state = globalState;
++ if (state->condition)
++ return state->value;
++ else
++ return state->worth;
++ }
++ \endcode
++
++ \sa operator->(), operator*()
++ */
++
++ /*!
++ \fn template <typename Holder> Type *QGlobalStatic<Holder>::operator()()
++ \deprecated
++
++ This function returns the address of the contents of this global static. If
++ the contents have not yet been created, they will be created thread-safely
++ by this function. If the contents have already been destroyed, this
++ function will return a null pointer.
++
++ This function is equivalent to \l {qglobalstatic-operator-type-ptr}
++ {operator Type *()}. It is provided for compatibility with the private
++ Q_GLOBAL_STATIC implementation that existed in Qt 4.x and 5.0. New code
++ should avoid using it and should instead treat the object as a smart
++ pointer.
++ */
++
++ /*!
++ \fn template <typename Holder> Type *QGlobalStatic<Holder>::operator->()
++
++ This function returns the address of the contents of this global static. If
++ the contents have not yet been created, they will be created thread-safely
++ by this function.
++
++ This function does not check if the contents have already been destroyed and
++ will never return null. If this function is called after the object has
++ been destroyed, it will return a dangling pointer that should not be
++ dereferenced.
++
++ \sa exists(), isDestroyed()
++ */
++
++ /*!
++ \fn template <typename Holder> Type &QGlobalStatic<Holder>::operator*()
++
++ This function returns a reference to the contents of this global static. If
++ the contents have not yet been created, they will be created thread-safely
++ by this function.
++
++ This function does not check if the contents have already been destroyed.
++ If this function is called after the object has been destroyed, it will
++ return an invalid reference that must not be used.
++
++ \sa exists(), isDestroyed()
++ */