File indexing completed on 2024-04-28 11:47:33

0001 /*
0002     SPDX-FileCopyrightText: 2011 Will Stephenson <wstephenson@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #ifndef MM_MACROS_H
0008 #define MM_MACROS_H
0009 
0010 #define MM_GLOBAL_STATIC_STRUCT_NAME(NAME)
0011 typedef void (*MmCleanUpFunction)();
0012 class MmCleanUpGlobalStatic
0013 {
0014 public:
0015     MmCleanUpFunction func;
0016 
0017     inline ~MmCleanUpGlobalStatic()
0018     {
0019         func();
0020     }
0021 };
0022 
0023 #define MM_GLOBAL_STATIC(TYPE, NAME) MM_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
0024 
0025 /* clang-format off */
0026 #define MM_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)                            \
0027 static QBasicAtomicPointer<TYPE > _mm_static_##NAME = Q_BASIC_ATOMIC_INITIALIZER(0); \
0028 static bool _mm_static_##NAME##_destroyed;                                      \
0029 static struct MM_GLOBAL_STATIC_STRUCT_NAME(NAME)                                \
0030 {                                                                              \
0031     inline bool isDestroyed() const                                            \
0032     {                                                                          \
0033         return _mm_static_##NAME##_destroyed;                                   \
0034     }                                                                          \
0035     inline bool exists() const                                                 \
0036     {                                                                          \
0037         return _mm_static_##NAME != 0;                                          \
0038     }                                                                          \
0039     inline operator TYPE*()                                                    \
0040     {                                                                          \
0041         return operator->();                                                   \
0042     }                                                                          \
0043     inline TYPE *operator->()                                                  \
0044     {                                                                          \
0045         if (!_mm_static_##NAME) {                                               \
0046             if (isDestroyed()) {                                               \
0047                 qFatal("Fatal Error: Accessed global static '%s *%s()' after destruction. " \
0048                        "Defined at %s:%d", #TYPE, #NAME, __FILE__, __LINE__);  \
0049             }                                                                  \
0050             TYPE *x = new TYPE ARGS;                                           \
0051             if (!_mm_static_##NAME.testAndSetOrdered(0, x)                      \
0052                 && _mm_static_##NAME != x ) {                                   \
0053                 delete x;                                                      \
0054             } else {                                                           \
0055                 static MmCleanUpGlobalStatic cleanUpObject = { destroy };       \
0056             }                                                                  \
0057         }                                                                      \
0058         return _mm_static_##NAME;                                               \
0059     }                                                                          \
0060     inline TYPE &operator*()                                                   \
0061     {                                                                          \
0062         return *operator->();                                                  \
0063     }                                                                          \
0064     static void destroy()                                                      \
0065     {                                                                          \
0066         _mm_static_##NAME##_destroyed = true;                                   \
0067         TYPE *x = _mm_static_##NAME;                                            \
0068         _mm_static_##NAME = 0;                                                  \
0069         delete x;                                                              \
0070     }                                                                          \
0071 } NAME;
0072 /* clang-format on */
0073 
0074 #endif