123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /******************************************************************************
- *
- * package: Log4Qt
- * file: initialisationhelper.h
- * created: September 2007
- * author: Martin Heinrich
- *
- *
- * changes: Sep 2008, Martin Heinrich:
- * - Replaced usage of q_atomic_test_and_set_ptr with
- * QBasicAtomicPointer
- *
- *
- * Copyright 2007 - 2008 Martin Heinrich
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
- #ifndef LOG4QT_HELPERS_INITIALISATIONHELPER_H
- #define LOG4QT_HELPERS_INITIALISATIONHELPER_H
- /******************************************************************************
- * Dependencies
- ******************************************************************************/
- #include <QtCore/QAtomicPointer>
- #include <QtCore/QHash>
- #include <QtCore/QString>
- #if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
- # ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
- # warning "QAtomicPointer test and set is not native. The macros Log4Qt::LOG4QT_GLOBAL_STATIC and Log4Qt::LOG4QT_IMPLEMENT_INSTANCE are not thread-safe."
- # endif
- #endif
- /******************************************************************************
- * Declarations
- ******************************************************************************/
- class QMutex;
- namespace Log4Qt
- {
- /*!
- * LOG4QT_GLOBAL_STATIC declares a static function \a FUNCTION that
- * returns a pointer to a singleton object of the type \a TYPE.
- *
- * The macro uses a static variable to store a pointer to the singleton
- * object. On the first invocation an object of the type \a TYPE is created
- * on the heap and the pointer is set. Any further invocations will return
- * the stored pointer. If multiple threads are accessing the function
- * without the pointer being set, each thread will create an object of the
- * type \a TYPE. The threads that find the pointer already been set will
- * delete their object. The singleton object will not be deleted during static
- * de-initialisation.
- *
- * The following example uses a global global mutex object to synchronise
- * access to a static member variable.
- *
- * \code
- * #file: myclass.h
- *
- * class MyClass
- * {
- * public:
- * MyClass();
- * ~MyClass();
- * private:
- * static qint64 msObjectCount;
- * }
- * \endcode
- * \code
- * #file: myclass.cpp
- *
- * #include myclass.h
- *
- * LOG4QT_GLOBAL_STATIC(QMutex, class_guard)
- *
- * MyClass::MyClass()
- * {
- * QMutexLocker(class_guard());
- * msObjectCount++;
- * }
- *
- * MyClass::~MyClass()
- * {
- * QMutexLocker(class_guard());
- * msObjectCount--;
- * }
- *
- * qint64 MyClass::msObjectCount = 0;
- * \endcode
- *
- * \note The function created by the macro is thread-safe.
- *
- * \sa \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE",
- * \ref Log4Qt::InitialisationHelper "InitialisationHelper"
- */
- #if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
- #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
- static volatile TYPE *sp_global_static_##FUNCTION = 0; \
- TYPE *FUNCTION() \
- { \
- if (!sp_global_static_##FUNCTION) \
- { \
- TYPE *p_temp = new TYPE; \
- if (!q_atomic_test_and_set_ptr(&sp_global_static_##FUNCTION, \
- 0, p_temp)) \
- delete p_temp; \
- } \
- return const_cast<TYPE *>(sp_global_static_##FUNCTION); \
- }
- #elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
- #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
- static QBasicAtomicPointer<TYPE > sp_global_static_##FUNCTION = \
- Q_BASIC_ATOMIC_INITIALIZER(0); \
- TYPE *FUNCTION() \
- { \
- if (!sp_global_static_##FUNCTION) \
- { \
- TYPE *p_temp = new TYPE; \
- if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \
- p_temp)) \
- delete p_temp; \
- } \
- return sp_global_static_##FUNCTION; \
- }
- #else
- #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
- static QBasicAtomicPointer<TYPE > sp_global_static_##FUNCTION = \
- Q_BASIC_ATOMIC_INITIALIZER(0); \
- TYPE *FUNCTION() \
- { \
- if (!sp_global_static_##FUNCTION.loadAcquire()) \
- { \
- TYPE *p_temp = new TYPE; \
- if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \
- p_temp)) \
- delete p_temp; \
- } \
- return sp_global_static_##FUNCTION.loadAcquire(); \
- }
- #endif
- /*!
- * LOG4QT_IMPLEMENT_INSTANCE implements an instance function for a
- * singleton class \a TYPE.
- *
- * The function works like the one created by
- * \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC".
- *
- * The following example illustrates how to use the macro to create a
- * singleton class:
- *
- * \code
- * #file: mysingleton.h
- *
- * class MySingleton
- * {
- * private:
- * MySingleton();
- * ~MySingleton();
- * public:
- * MySingleton *instance();
- * }
- * \endcode
- * \code
- * #file: mysingleton.cpp
- *
- * #include mysingleton.h
- *
- * MySingleton::MySingleton()
- * {}
- *
- * MySingleton::~MySingleton()
- * {}
- *
- * LOG4QT_IMPLEMENT_INSTANCE(MySingleton)
- *
- * \endcode
- *
- * \note The function created by the macro is thread-safe.
- *
- * \sa \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC",
- * \ref Log4Qt::InitialisationHelper "InitialisationHelper"
- */
- #if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
- #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
- static TYPE *sp_singleton_##TYPE = 0; \
- TYPE *TYPE::instance() \
- { \
- if (!sp_singleton_##TYPE) \
- { \
- TYPE *p_temp = new TYPE; \
- if (!q_atomic_test_and_set_ptr(&sp_singleton_##TYPE, \
- 0, p_temp)) \
- delete p_temp; \
- } \
- return sp_singleton_##TYPE; \
- }
- #elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
- #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
- static QBasicAtomicPointer<TYPE > sp_singleton_##TYPE = \
- Q_BASIC_ATOMIC_INITIALIZER(0); \
- TYPE *TYPE::instance() \
- { \
- if (!sp_singleton_##TYPE) \
- { \
- TYPE *p_temp = new TYPE; \
- if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \
- delete p_temp; \
- } \
- return sp_singleton_##TYPE; \
- }
- #else
- #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
- static QBasicAtomicPointer<TYPE > sp_singleton_##TYPE = \
- Q_BASIC_ATOMIC_INITIALIZER(0); \
- TYPE *TYPE::instance() \
- { \
- if (!sp_singleton_##TYPE.loadAcquire()) \
- { \
- TYPE *p_temp = new TYPE; \
- if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \
- delete p_temp; \
- } \
- return sp_singleton_##TYPE.loadAcquire(); \
- }
- #endif
- /*!
- * \brief The class InitialisationHelper performs static initialisation
- * tasks.
- *
- * The InitialisationHelper is either created on the first call or through
- * static initialisation. It will capture the programs startup time,
- * which can be retrieved using startTime(). The system environment
- * is analysed for package related definitions. The result is available
- * over environmentSettings(). The packages custom types are registered with
- * the Qt type system.
- *
- * Settings for the package can be retrieved using setting(). Two macros
- * are available to help with the creation of singletons / global static
- * objects (\ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" and
- * \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE").
- *
- * \note All the functions declared in this class are thread-safe.
- *
- * \sa \ref Init "Initialization procedure",
- */
- class InitialisationHelper
- {
- private:
- InitialisationHelper();
- InitialisationHelper(const InitialisationHelper &rOther); // Not implemented
- virtual ~InitialisationHelper();
- InitialisationHelper &operator=(const InitialisationHelper &rOther); // Not implemented
- public:
- /*!
- * Returns a hash with the settings retrieved from the system
- * environment on startup.
- *
- * The following table shows the environment variables taken into
- * account and the setting key used for them.
- *
- * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
- * <tr bgcolor="#d5e1e8">
- * <th width="25%"> Environment variable </th>
- * <th width="25%"> Setting key </th>
- * </tr><tr>
- * <td> LOG4QT_DEBUG </td>
- * <td> Debug </td>
- * </tr><tr bgcolor="#ffffff">
- * <td> LOG4QT_DEFAULTINITOVERRIDE </td>
- * <td> DefaultInitOverride </td>
- * </tr><tr>
- * <td> LOG4QT_CONFIGURATION </td>
- * <td> Configuration </td>
- * </tr><tr bgcolor="#ffffff">
- * <td> LOG4QT_CONFIGURATORCLASS </td>
- * <td> ConfiguratorClass </td>
- * </tr>
- * </table>
- *
- * \sa \ref Env "Environment Variables",
- * setting()
- */
- static QHash<QString, QString> environmentSettings();
- /*!
- * Returns the InitialisationHelper instance.
- */
- static InitialisationHelper *instance();
- /*!
- * Returns the value for the setting \a rKey or \a rDefault, if it is
- * not defined.
- *
- * A setting can be either defined by an environment variable or by a
- * key in the application setting. The function will first test the
- * settings made by environment variables for the key \a rKey using
- * environmentSettings(). If the key is not present and a
- * QCoreApplication exists, the application settings are tested for
- * the key \a rKey in the group \c %Log4Qt.
- *
- * The following setting exists:
- *
- * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
- * <tr bgcolor="#d5e1e8">
- * <th width="25%"> Setting key </th>
- * <th> Description </th>
- * </tr><tr>
- * <td> Debug </td>
- * <td> The variable controls the Level value for the logger
- * LogManager::logLogger(). If the value is a valid Level string,
- * the level for the logger is set to the level. If the value is not
- * a valid Level string, \ref Level::DEBUG_INT "DEBUG_INT" is used.
- * Otherwise \ref Level::ERROR_INT "ERROR_INT" is used. </td>
- * </tr><tr bgcolor="#ffffff">
- * <td> DefaultInitOverride </td>
- * <td> The variable controls the \ref Init "initialization procedure"
- * performed by the \ref LogManager "LogManager" on startup.
- * If it is set to any other value then \c false the \ref Init
- * "initialization procedure" is skipped.</td>
- * </tr><tr>
- * <td> Configuration </td>
- * <td> Specifies the configuration file used for initialising the package.</td>
- * </tr><tr bgcolor="#ffffff">
- * <td> ConfiguratorClass </td>
- * <td> Specifies the configurator class used for initialising the package.</td>
- * </tr>
- * </table>
- *
- * \sa environmentSettings(), \ref Env "Environment Variables",
- * \ref Init "Initialization procedure",
- * LogManager::configureLogLogger(), LogManager::startup()
- */
- static QString setting(const QString &rKey,
- const QString &rDefault = QString());
- /*!
- * Returns the start time of the program as the number of milliseconds
- * that have passed since 1970-01-01T00:00:00,000, Coordinated
- * Universal Time (Qt::UTC).
- *
- * \sa DateTime::fromMilliSeconds(),
- * DateTime::toMilliSeconds()
- */
- static qint64 startTime();
- private:
- void doInitialiseEnvironmentSettings();
- void doRegisterTypes();
- QString doSetting(const QString &rKey,
- const QString &rDefault) const;
- static bool shutdown();
- static bool staticInitialisation();
- private:
- // QMutex mObjectGuard;
- const qint64 mStartTime;
- QHash <QString, QString> mEnvironmentSettings;
- static bool msStaticInitialisation;
- #ifndef QT_NO_DEBUG_STREAM
- // Needs to be friend to access details
- friend QDebug operator<<(QDebug debug,
- const InitialisationHelper &rInitialisationHelper);
- #endif // QT_NO_DEBUG_STREAM
- };
- /**************************************************************************
- * Operators, Helper
- **************************************************************************/
- #ifndef QT_NO_DEBUG_STREAM
- /*!
- * \relates InitialisationHelper
- *
- * Writes all object member variables to the given debug stream \a rDebug and
- * returns the stream.
- *
- * <tt>
- * %InitialisationHelper(InitialisationHelper(starttime:1193883677438(
- * QDateTime("Wed Oct 31 21:21:17 2007") )
- * environmentsettings: QHash(("configuration", "\myapp.log4j")
- * ("Debug", "DEBUG")) ) )
- * </tt>
- * \sa QDebug, InitialisationHelper::logManager()
- */
- QDebug operator<<(QDebug debug,
- const InitialisationHelper &rInitialisationHelper);
- #endif // QT_NO_DEBUG_STREAM
- /**************************************************************************
- * Inline
- **************************************************************************/
- inline QHash<QString, QString> InitialisationHelper::environmentSettings()
- { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
- return instance()->mEnvironmentSettings; }
- inline QString InitialisationHelper::setting(const QString &rKey,
- const QString &rDefault)
- { // QMutexLocker locker(&instance()->mObjectGuard); // Reentrant and const
- return instance()->doSetting(rKey, rDefault); }
- inline qint64 InitialisationHelper::startTime()
- { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
- return instance()->mStartTime; }
- } // namespace Log4Qt
- // Q_DECLARE_TYPEINFO(Log4Qt::InitialisationHelper, Q_COMPLEX_TYPE); // use default
- #endif // LOG4QT_HELPERS_INITIALISATIONHELPER_H
|