From 8b080e59c5019112f5699db5c2c101f76b3da88f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 11 May 2017 15:39:15 +0200 Subject: rename qglobalstatic.cpp -> qglobalstatic.qdoc it contains no code. Change-Id: Ie8a43abb2db3d040f7046206adf2bf555960dd9c Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira --- src/corelib/global/global.pri | 1 - src/corelib/global/qglobalstatic.cpp | 522 ---------------------------------- src/corelib/global/qglobalstatic.qdoc | 520 +++++++++++++++++++++++++++++++++ 3 files changed, 520 insertions(+), 523 deletions(-) delete mode 100644 src/corelib/global/qglobalstatic.cpp create mode 100644 src/corelib/global/qglobalstatic.qdoc diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index f162dd95dd..b76d1ef43c 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -27,7 +27,6 @@ HEADERS += \ SOURCES += \ global/archdetect.cpp \ global/qglobal.cpp \ - global/qglobalstatic.cpp \ global/qlibraryinfo.cpp \ global/qmalloc.cpp \ global/qnumeric.cpp \ diff --git a/src/corelib/global/qglobalstatic.cpp b/src/corelib/global/qglobalstatic.cpp deleted file mode 100644 index d1c522a79a..0000000000 --- a/src/corelib/global/qglobalstatic.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobalstatic.h" - -/*! - \macro Q_GLOBAL_STATIC(Type, VariableName) - \since 5.1 - \relates QGlobalStatic - - Creates a global and static object of type \l QGlobalStatic, of name \a - VariableName and that 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. - - The typical use of this macro is as follows, in a global context (that is, - outside of any function bodies): - - \code - Q_GLOBAL_STATIC(MyType, staticType) - \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 staticType; - \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 - above has the following drawbacks: - - \list - \li it requires load-time initialization of \c MyType (that is, the - default constructor for \c MyType is called when the library or - application is loaded); - - \li the type 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; - - \li if it is found inside a function (that is, not global), it will be - initialized on first use, but many current compilers (as of 2013) do - not guarantee that the initialization will be thread-safe; - \endlist - - The Q_GLOBAL_STATIC macro solves all of the above 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 QGlobalStatic::isDestroyed()). - - \section1 Constructor and Destructor - - For Q_GLOBAL_STATIC, the type \c Type must be publicly - default-constructible and publicly destructible. For - Q_GLOBAL_STATIC_WITH_ARGS(), there must be a public constructor that - matches the arguments passed. - - It is not possible to use Q_GLOBAL_STATIC with types that have protected or - private default constructors or destructors (for Q_GLOBAL_STATIC_WITH_ARGS(), - a protected or private constructor matching the arguments). If the type in - question has those members as protected, it is possible to overcome the - issue by deriving from the type and creating public a constructor and - destructor. If the type has them as 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 has them as private, but that defines \c - MyType as a friend). - - \code - class MyType : public MyOtherType { }; - Q_GLOBAL_STATIC(MyType, staticType) - \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 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_WITH_ARGS(MyType, staticType, (42)) - \endcode - - Alternatively, if the compiler supports C++11 inheriting constructors, one could write: - - \code - class MyType : public MyOtherType - { - public: - using MyOtherType::MyOtherType; - }; - Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42)) - \endcode - - \section1 Placement - - The Q_GLOBAL_STATIC macro creates a type that is necessarily static, at the - global scope. It is not possible to place the Q_GLOBAL_STATIC macro inside - a function (doing so will result in compilation errors). - - More importantly, this macro should be placed in source files, never in - headers. Since the resulting object is 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 the - 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 form and 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 QBasicAtomicInt called the \c - guard and a free, inline function called \c innerFunction. The guard - variable is initialized to value 0 (chosen so that the guard can be placed - in the .bss section of the binary file), which denotes that construction - has not yet taken place (uninitialized). The inner function is implemented - by the helper macro Q_GLOBAL_STATIC_INTERNAL. - - Both the guard variable and the inner function are passed as template - parameters to QGlobalStatic, along with the type \a Type. Both should also - have static linkage or be placed inside an anonymous namespace, so that the - visibility of Q_GLOBAL_STATIC is that of a global static. To permit - multiple Q_GLOBAL_STATIC per translation unit, the guard variable and the - inner function must have unique names, which can be accomplished by - concatenating with \a VariableName or by placing them in a namespace that - has \a VariableName as part of the name. To simplify and improve - readability on Q_GLOBAL_STATIC_INTERNAL, we chose the namespace solution. - It's also required for C++98 builds, since static symbols cannot be used as - template parameters. - - 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 negative, whereas the latter returns \c true only if it is -2. - - The Q_GLOBAL_STATIC_INTERNAL macro implements the actual construction and - destruction. There are two implementations of it: one for compilers that - support thread-safe initialization of function-local statics and one for - compilers that don't. Thread-safe initialization is required by C++11 in - [stmt.decl], but as of the time of this writing, only compilers based on - the IA-64 C++ ABI implemented it properly. The implementation requiring - thread-safe initialization is also used on the Qt bootstrapped tools, which - define QT_NO_THREAD. - - The implementation requiring thread-safe initialization from the compiler - is the simplest: it creates the \a Type object as a function-local static - and returns its address. The actual object is actually inside a holder - structure so holder's destructor can set the guard variable to the value -2 - (destroyed) when the type has finished destruction. Since we need to set - the guard \b after the destruction has finished, this code needs to be in a - base struct's destructor. And it only sets to -2 (destroyed) if it finds - the guard at -1 (initialized): this is done to ensure that the guard isn't - set to -2 in the event the type's constructor threw an exception. A holder - structure is used to avoid creating two statics, which the ABI might - require duplicating the thread-safe control structures for. - - The other implementation is similar to Qt 4's Q_GLOBAL_STATIC, but unlike - that one, it uses a \l QBasicMutex to provide locking. It is also more - efficient memory-wise. It use a simple double-checked locking of the mutex - and then creates the contents on the heap. After that, it creates a - function-local structure called "Cleanup", whose destructor will be run at - program exit and will actually destroy the contents. - - \endomit - - \sa Q_GLOBAL_STATIC_WITH_ARGS(), QGlobalStatic -*/ - -/*! - \macro Q_GLOBAL_STATIC_WITH_ARGS(Type, VariableName, Arguments) - \since 5.1 - \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, - outside of any function bodies): - - \code - Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42, "Hello", "World")) - \endcode - - The \a Arguments macro parameter must always include the parentheses or, if - C++11 uniform initialization is allowed, the braces. - - Aside from the actual initialization of the contents with the supplied - arguments, 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 - - The QGlobalStatic class is the front-end API exported when - Q_GLOBAL_STATIC() is used. See the documentation for the macro for a - discussion on when to use it and its requirements. - - Normally, you will never use this class directly, but instead you will use - the Q_GLOBAL_STATIC() or Q_GLOBAL_STATIC_WITH_ARGS() macros, as - follows: - - \code - Q_GLOBAL_STATIC(MyType, staticType) - \endcode - - The above example creates an object of type QGlobalStatic called \c - staticType. After the above declaration, the \c staticType object may be - used as if it were a pointer, 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(), Q_GLOBAL_STATIC_WITH_ARGS() -*/ - -/*! - \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 bool QGlobalStatic::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 specific, 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 bool QGlobalStatic::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). In specific, 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 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 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() -*/ - -/*! - \fn QGlobalStatic::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() - { - MyType *state = globalState; - if (!state) { - // we're in a post-destruction state - return QString(); - } - if (state->condition) - return state->value1; - else - return state->value2; - } - \endcode - - \sa operator->(), operator*() -*/ - -/*! - \fn Type *QGlobalStatic::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 {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 Type *QGlobalStatic::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. -*/ - -/*! - \fn Type &QGlobalStatic::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. -*/ diff --git a/src/corelib/global/qglobalstatic.qdoc b/src/corelib/global/qglobalstatic.qdoc new file mode 100644 index 0000000000..8c34739d38 --- /dev/null +++ b/src/corelib/global/qglobalstatic.qdoc @@ -0,0 +1,520 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \macro Q_GLOBAL_STATIC(Type, VariableName) + \since 5.1 + \relates QGlobalStatic + + Creates a global and static object of type \l QGlobalStatic, of name \a + VariableName and that 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. + + The typical use of this macro is as follows, in a global context (that is, + outside of any function bodies): + + \code + Q_GLOBAL_STATIC(MyType, staticType) + \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 staticType; + \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 + above has the following drawbacks: + + \list + \li it requires load-time initialization of \c MyType (that is, the + default constructor for \c MyType is called when the library or + application is loaded); + + \li the type 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; + + \li if it is found inside a function (that is, not global), it will be + initialized on first use, but many current compilers (as of 2013) do + not guarantee that the initialization will be thread-safe; + \endlist + + The Q_GLOBAL_STATIC macro solves all of the above 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 QGlobalStatic::isDestroyed()). + + \section1 Constructor and Destructor + + For Q_GLOBAL_STATIC, the type \c Type must be publicly + default-constructible and publicly destructible. For + Q_GLOBAL_STATIC_WITH_ARGS(), there must be a public constructor that + matches the arguments passed. + + It is not possible to use Q_GLOBAL_STATIC with types that have protected or + private default constructors or destructors (for Q_GLOBAL_STATIC_WITH_ARGS(), + a protected or private constructor matching the arguments). If the type in + question has those members as protected, it is possible to overcome the + issue by deriving from the type and creating public a constructor and + destructor. If the type has them as 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 has them as private, but that defines \c + MyType as a friend). + + \code + class MyType : public MyOtherType { }; + Q_GLOBAL_STATIC(MyType, staticType) + \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 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_WITH_ARGS(MyType, staticType, (42)) + \endcode + + Alternatively, if the compiler supports C++11 inheriting constructors, one could write: + + \code + class MyType : public MyOtherType + { + public: + using MyOtherType::MyOtherType; + }; + Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42)) + \endcode + + \section1 Placement + + The Q_GLOBAL_STATIC macro creates a type that is necessarily static, at the + global scope. It is not possible to place the Q_GLOBAL_STATIC macro inside + a function (doing so will result in compilation errors). + + More importantly, this macro should be placed in source files, never in + headers. Since the resulting object is 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 the + 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 form and 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 QBasicAtomicInt called the \c + guard and a free, inline function called \c innerFunction. The guard + variable is initialized to value 0 (chosen so that the guard can be placed + in the .bss section of the binary file), which denotes that construction + has not yet taken place (uninitialized). The inner function is implemented + by the helper macro Q_GLOBAL_STATIC_INTERNAL. + + Both the guard variable and the inner function are passed as template + parameters to QGlobalStatic, along with the type \a Type. Both should also + have static linkage or be placed inside an anonymous namespace, so that the + visibility of Q_GLOBAL_STATIC is that of a global static. To permit + multiple Q_GLOBAL_STATIC per translation unit, the guard variable and the + inner function must have unique names, which can be accomplished by + concatenating with \a VariableName or by placing them in a namespace that + has \a VariableName as part of the name. To simplify and improve + readability on Q_GLOBAL_STATIC_INTERNAL, we chose the namespace solution. + It's also required for C++98 builds, since static symbols cannot be used as + template parameters. + + 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 negative, whereas the latter returns \c true only if it is -2. + + The Q_GLOBAL_STATIC_INTERNAL macro implements the actual construction and + destruction. There are two implementations of it: one for compilers that + support thread-safe initialization of function-local statics and one for + compilers that don't. Thread-safe initialization is required by C++11 in + [stmt.decl], but as of the time of this writing, only compilers based on + the IA-64 C++ ABI implemented it properly. The implementation requiring + thread-safe initialization is also used on the Qt bootstrapped tools, which + define QT_NO_THREAD. + + The implementation requiring thread-safe initialization from the compiler + is the simplest: it creates the \a Type object as a function-local static + and returns its address. The actual object is actually inside a holder + structure so holder's destructor can set the guard variable to the value -2 + (destroyed) when the type has finished destruction. Since we need to set + the guard \b after the destruction has finished, this code needs to be in a + base struct's destructor. And it only sets to -2 (destroyed) if it finds + the guard at -1 (initialized): this is done to ensure that the guard isn't + set to -2 in the event the type's constructor threw an exception. A holder + structure is used to avoid creating two statics, which the ABI might + require duplicating the thread-safe control structures for. + + The other implementation is similar to Qt 4's Q_GLOBAL_STATIC, but unlike + that one, it uses a \l QBasicMutex to provide locking. It is also more + efficient memory-wise. It use a simple double-checked locking of the mutex + and then creates the contents on the heap. After that, it creates a + function-local structure called "Cleanup", whose destructor will be run at + program exit and will actually destroy the contents. + + \endomit + + \sa Q_GLOBAL_STATIC_WITH_ARGS(), QGlobalStatic +*/ + +/*! + \macro Q_GLOBAL_STATIC_WITH_ARGS(Type, VariableName, Arguments) + \since 5.1 + \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, + outside of any function bodies): + + \code + Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42, "Hello", "World")) + \endcode + + The \a Arguments macro parameter must always include the parentheses or, if + C++11 uniform initialization is allowed, the braces. + + Aside from the actual initialization of the contents with the supplied + arguments, 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 + + The QGlobalStatic class is the front-end API exported when + Q_GLOBAL_STATIC() is used. See the documentation for the macro for a + discussion on when to use it and its requirements. + + Normally, you will never use this class directly, but instead you will use + the Q_GLOBAL_STATIC() or Q_GLOBAL_STATIC_WITH_ARGS() macros, as + follows: + + \code + Q_GLOBAL_STATIC(MyType, staticType) + \endcode + + The above example creates an object of type QGlobalStatic called \c + staticType. After the above declaration, the \c staticType object may be + used as if it were a pointer, 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(), Q_GLOBAL_STATIC_WITH_ARGS() +*/ + +/*! + \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 bool QGlobalStatic::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 specific, 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 bool QGlobalStatic::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). In specific, 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 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 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() +*/ + +/*! + \fn QGlobalStatic::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() + { + MyType *state = globalState; + if (!state) { + // we're in a post-destruction state + return QString(); + } + if (state->condition) + return state->value1; + else + return state->value2; + } + \endcode + + \sa operator->(), operator*() +*/ + +/*! + \fn Type *QGlobalStatic::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 {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 Type *QGlobalStatic::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. +*/ + +/*! + \fn Type &QGlobalStatic::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. +*/ -- cgit v1.2.3