summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/phonon/phonon/globalstatic_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/phonon/phonon/globalstatic_p.h')
-rw-r--r--src/3rdparty/phonon/phonon/globalstatic_p.h293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/3rdparty/phonon/phonon/globalstatic_p.h b/src/3rdparty/phonon/phonon/globalstatic_p.h
new file mode 100644
index 0000000000..04f83955bc
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/globalstatic_p.h
@@ -0,0 +1,293 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Trolltech ASA
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_GLOBALSTATIC_P_H
+#define PHONON_GLOBALSTATIC_P_H
+
+#include <QtCore/QAtomicPointer>
+
+//
+// WARNING!!
+// This code uses undocumented Qt API
+// Do not copy it to your application! Use only the functions that are here!
+// Otherwise, it could break when a new version of Qt ships.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+/**
+ * @internal
+ */
+typedef void (*CleanUpFunction)();
+
+/**
+ * @internal
+ *
+ * Helper class for PHONON_GLOBAL_STATIC to clean up the object on library unload or application
+ * shutdown.
+ */
+class CleanUpGlobalStatic
+{
+ public:
+ CleanUpFunction func;
+
+ inline ~CleanUpGlobalStatic() { func(); }
+};
+
+} // namespace Phonon
+
+#ifdef Q_CC_MSVC
+/**
+ * @internal
+ *
+ * MSVC seems to give anonymous structs the same name which fails at link time. So instead we name
+ * the struct and hope that by adding the line number to the name it's unique enough to never clash.
+ */
+# define PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME) _k_##NAME##__LINE__
+#else
+/**
+ * @internal
+ *
+ * Make the struct of the PHONON_GLOBAL_STATIC anonymous.
+ */
+# define PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME)
+#endif
+
+/**
+ * This macro makes it easy to use non-POD types as global statics.
+ * The object is created on first use and creation is threadsafe.
+ *
+ * The object is destructed on library unload or application exit.
+ * Be careful with calling other objects in the destructor of the class
+ * as you have to be sure that they (or objects they depend on) are not already destructed.
+ *
+ * @param TYPE The type of the global static object. Do not add a *.
+ * @param NAME The name of the function to get a pointer to the global static object.
+ *
+ * If you have code that might be called after the global object has been destroyed you can check
+ * for that using the isDestroyed() function.
+ *
+ * If needed (If the destructor of the global object calls other functions that depend on other
+ * global statics (e.g. KConfig::sync) your destructor has to be called before those global statics
+ * are destroyed. A Qt post routine does that.) you can also install a post routine (@ref qAddPostRoutine) to clean up the object
+ * using the destroy() method. If you registered a post routine and the object is destroyed because
+ * of a lib unload you have to call qRemovePostRoutine!
+ *
+ * Example:
+ * @code
+ * class A {
+ * public:
+ * ~A();
+ * ...
+ * };
+ *
+ * PHONON_GLOBAL_STATIC(A, globalA)
+ * // The above creates a new globally static variable named 'globalA' which you
+ * // can use as a pointer to an instance of A.
+ *
+ * void doSomething()
+ * {
+ * // The first time you access globalA a new instance of A will be created automatically.
+ * A *a = globalA;
+ * ...
+ * }
+ *
+ * void doSomethingElse()
+ * {
+ * if (globalA.isDestroyed()) {
+ * return;
+ * }
+ * A *a = globalA;
+ * ...
+ * }
+ *
+ * void installPostRoutine()
+ * {
+ * // A post routine can be used to delete the object when QCoreApplication destructs,
+ * // not adding such a post routine will delete the object normally at program unload
+ * qAddPostRoutine(globalA.destroy);
+ * }
+ *
+ * A::~A()
+ * {
+ * // When you install a post routine you have to remove the post routine from the destructor of
+ * // the class used as global static!
+ * qRemovePostRoutine(globalA.destroy);
+ * }
+ * @endcode
+ *
+ * A common case for the need of deletion on lib unload/app shutdown are Singleton classes. Here's
+ * an example how to do it:
+ * @code
+ * class MySingletonPrivate;
+ * class EXPORT_MACRO MySingleton
+ * {
+ * friend class MySingletonPrivate;
+ * public:
+ * static MySingleton *self();
+ * QString someFunction();
+ *
+ * private:
+ * MySingleton();
+ * ~MySingleton();
+ * };
+ * @endcode
+ * in the .cpp file:
+ * @code
+ * // This class will be instantiated and referenced as a singleton in this example
+ * class MySingletonPrivate
+ * {
+ * public:
+ * QString foo;
+ * MySingleton instance;
+ * };
+ *
+ * PHONON_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate)
+ *
+ * MySingleton *MySingleton::self()
+ * {
+ * // returns the singleton; automatically creates a new instance if that has not happened yet.
+ * return &mySingletonPrivate->instance;
+ * }
+ * QString MySingleton::someFunction()
+ * {
+ * // Refencing the singleton directly is possible for your convenience
+ * return mySingletonPrivate->foo;
+ * }
+ * @endcode
+ *
+ * Instead of the above you can use also the following pattern (ignore the name of the namespace):
+ * @code
+ * namespace MySingleton
+ * {
+ * EXPORT_MACRO QString someFunction();
+ * }
+ * @endcode
+ * in the .cpp file:
+ * @code
+ * class MySingletonPrivate
+ * {
+ * public:
+ * QString foo;
+ * };
+ *
+ * PHONON_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate)
+ *
+ * QString MySingleton::someFunction()
+ * {
+ * return mySingletonPrivate->foo;
+ * }
+ * @endcode
+ *
+ * Now code that wants to call someFunction() doesn't have to do
+ * @code
+ * MySingleton::self()->someFunction();
+ * @endcode
+ * anymore but instead:
+ * @code
+ * MySingleton::someFunction();
+ * @endcode
+ *
+ * @ingroup KDEMacros
+ */
+#define PHONON_GLOBAL_STATIC(TYPE, NAME) PHONON_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
+
+/**
+ * @overload
+ * This is the same as PHONON_GLOBAL_STATIC, but can take arguments that are passed
+ * to the object's constructor
+ *
+ * @param TYPE The type of the global static object. Do not add a *.
+ * @param NAME The name of the function to get a pointer to the global static object.
+ * @param ARGS the list of arguments, between brackets
+ *
+ * Example:
+ * @code
+ * class A
+ * {
+ * public:
+ * A(const char *s, int i);
+ * ...
+ * };
+ *
+ * PHONON_GLOBAL_STATIC_WITH_ARG(A, globalA, ("foo", 0))
+ * // The above creates a new globally static variable named 'globalA' which you
+ * // can use as a pointer to an instance of A.
+ *
+ * void doSomething()
+ * {
+ * // The first time you access globalA a new instance of A will be created automatically.
+ * A *a = globalA;
+ * ...
+ * }
+ * @endcode
+ *
+ * @ingroup KDEMacros
+ */
+#define PHONON_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
+static QBasicAtomicPointer<TYPE > _k_static_##NAME = Q_BASIC_ATOMIC_INITIALIZER(0); \
+static bool _k_static_##NAME##_destroyed; \
+static struct PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME) \
+{ \
+ bool isDestroyed() \
+ { \
+ return _k_static_##NAME##_destroyed; \
+ } \
+ inline operator TYPE*() \
+ { \
+ return operator->(); \
+ } \
+ inline TYPE *operator->() \
+ { \
+ TYPE *p = _k_static_##NAME; \
+ if (!p) { \
+ if (isDestroyed()) { \
+ qFatal("Fatal Error: Accessed global static '%s *%s()' after destruction. " \
+ "Defined at %s:%d", #TYPE, #NAME, __FILE__, __LINE__); \
+ } \
+ p = new TYPE ARGS; \
+ if (!_k_static_##NAME.testAndSetOrdered(0, p)) { \
+ delete p; \
+ p = _k_static_##NAME; \
+ } else { \
+ static Phonon::CleanUpGlobalStatic cleanUpObject = { destroy }; \
+ } \
+ } \
+ return p; \
+ } \
+ inline TYPE &operator*() \
+ { \
+ return *operator->(); \
+ } \
+ static void destroy() \
+ { \
+ _k_static_##NAME##_destroyed = true; \
+ TYPE *x = _k_static_##NAME; \
+ _k_static_##NAME = 0; \
+ delete x; \
+ } \
+} NAME;
+
+QT_END_NAMESPACE
+#endif // PHONON_GLOBALSTATIC_P_H