File indexing completed on 2024-03-24 04:03:00

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 NETWORKMANAGERQT_MACROS_H
0008 #define NETWORKMANAGERQT_MACROS_H
0009 
0010 #define NM_GLOBAL_STATIC_STRUCT_NAME(NAME)
0011 typedef void (*NmCleanUpFunction)();
0012 class NmCleanUpGlobalStatic
0013 {
0014 public:
0015     NmCleanUpFunction func;
0016 
0017     inline ~NmCleanUpGlobalStatic()
0018     {
0019         func();
0020     }
0021 };
0022 
0023 #define NM_GLOBAL_STATIC(TYPE, NAME) NM_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
0024 
0025 /* clang-format off */
0026 #define NM_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)                            \
0027     static QBasicAtomicPointer<TYPE > _nm_static_##NAME = Q_BASIC_ATOMIC_INITIALIZER(0); \
0028     static bool _nm_static_##NAME##_destroyed;                                      \
0029     static struct NM_GLOBAL_STATIC_STRUCT_NAME(NAME)                                \
0030     {                                                                              \
0031         inline bool isDestroyed() const                                            \
0032         {                                                                          \
0033             return _nm_static_##NAME##_destroyed;                                   \
0034         }                                                                          \
0035         inline bool exists() const                                                 \
0036         {                                                                          \
0037             return _nm_static_##NAME != 0;                                          \
0038         }                                                                          \
0039         inline operator TYPE*()                                                    \
0040         {                                                                          \
0041             return operator->();                                                   \
0042         }                                                                          \
0043         inline TYPE *operator->()                                                  \
0044         {                                                                          \
0045             if (!_nm_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 (!_nm_static_##NAME.testAndSetOrdered(0, x)                      \
0052                         && _nm_static_##NAME != x ) {                                   \
0053                     delete x;                                                      \
0054                 } else {                                                           \
0055                     static NmCleanUpGlobalStatic cleanUpObject = { destroy };       \
0056                 }                                                                  \
0057             }                                                                      \
0058             return _nm_static_##NAME;                                               \
0059         }                                                                          \
0060         inline TYPE &operator*()                                                   \
0061         {                                                                          \
0062             return *operator->();                                                  \
0063         }                                                                          \
0064         static void destroy()                                                      \
0065         {                                                                          \
0066             _nm_static_##NAME##_destroyed = true;                                   \
0067             TYPE *x = _nm_static_##NAME;                                            \
0068             _nm_static_##NAME = 0;                                                  \
0069             delete x;                                                              \
0070         }                                                                          \
0071     } NAME;
0072 /* clang-format on */
0073 
0074 #endif