Add Q_COREAPP_STARTUP_FUNCTION macro.
This is necessary for initializing things in a library, which require a QCoreApplication instance (unlike Q_CONSTRUCTOR_FUNCTION, which runs before that). Example use cases: KCrash (segv handler), and KCheckAccelerators (debugging tool triggered by magic key combination). Change-Id: I5f4c4699dd4d21aea72b007989ba57467e86ed10 Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
3a1f1aecf9
commit
d147285d64
@ -57,7 +57,14 @@ foreach (const QString &path, app.libraryPaths())
|
||||
|
||||
|
||||
//! [3]
|
||||
// Called once QCoreApplication exists
|
||||
static void preRoutineMyDebugTool()
|
||||
{
|
||||
MyDebugTool* tool = new MyDebugTool(QCoreApplication::instance());
|
||||
QCoreApplication::instance()->installEventFilter(tool);
|
||||
}
|
||||
|
||||
Q_COREAPP_STARTUP_FUNCTION(preRoutineMyDebugTool)
|
||||
//! [3]
|
||||
|
||||
|
||||
|
@ -194,8 +194,32 @@ extern "C" void Q_CORE_EXPORT qt_startup_hook()
|
||||
{
|
||||
}
|
||||
|
||||
typedef QList<QtStartUpFunction> QStartUpFuncList;
|
||||
Q_GLOBAL_STATIC(QStartUpFuncList, preRList)
|
||||
typedef QList<QtCleanUpFunction> QVFuncList;
|
||||
Q_GLOBAL_STATIC(QVFuncList, postRList)
|
||||
static QBasicMutex globalPreRoutinesMutex;
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Adds a global routine that will be called from the QCoreApplication
|
||||
constructor. The public API is Q_COREAPP_STARTUP_FUNCTION.
|
||||
*/
|
||||
void qAddPreRoutine(QtStartUpFunction p)
|
||||
{
|
||||
QStartUpFuncList *list = preRList();
|
||||
if (!list)
|
||||
return;
|
||||
// Due to C++11 parallel dynamic initialization, this can be called
|
||||
// from multiple threads.
|
||||
#ifndef QT_NO_THREAD
|
||||
QMutexLocker locker(&globalPreRoutinesMutex);
|
||||
#endif
|
||||
if (QCoreApplication::instance())
|
||||
p();
|
||||
list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
|
||||
}
|
||||
|
||||
void qAddPostRoutine(QtCleanUpFunction p)
|
||||
{
|
||||
@ -213,6 +237,21 @@ void qRemovePostRoutine(QtCleanUpFunction p)
|
||||
list->removeAll(p);
|
||||
}
|
||||
|
||||
static void qt_call_pre_routines()
|
||||
{
|
||||
QStartUpFuncList *list = preRList();
|
||||
if (!list)
|
||||
return;
|
||||
#ifndef QT_NO_THREAD
|
||||
QMutexLocker locker(&globalPreRoutinesMutex);
|
||||
#endif
|
||||
// Unlike qt_call_post_routines, we don't empty the list, because
|
||||
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
|
||||
// the function to be executed every time QCoreApplication is created.
|
||||
for (int i = 0; i < list->count(); ++i)
|
||||
list->at(i)();
|
||||
}
|
||||
|
||||
void Q_CORE_EXPORT qt_call_post_routines()
|
||||
{
|
||||
QVFuncList *list = 0;
|
||||
@ -637,6 +676,7 @@ void QCoreApplication::init()
|
||||
|
||||
d->processCommandLineArguments();
|
||||
|
||||
qt_call_pre_routines();
|
||||
qt_startup_hook();
|
||||
}
|
||||
|
||||
@ -2324,6 +2364,31 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
|
||||
mainThread->setEventDispatcher(eventDispatcher);
|
||||
}
|
||||
|
||||
/*!
|
||||
\macro Q_COREAPP_STARTUP_FUNCTION(QtStartUpFunction ptr)
|
||||
\since 5.1
|
||||
\relates QCoreApplication
|
||||
\reentrant
|
||||
|
||||
Adds a global function that will be called from the QCoreApplication
|
||||
constructor. This macro is normally used to initialize libraries
|
||||
for program-wide functionality, without requiring the application to
|
||||
call into the library for initialization.
|
||||
|
||||
The function specified by \a ptr should take no arguments and should
|
||||
return nothing. For example:
|
||||
|
||||
\snippet code/src_corelib_kernel_qcoreapplication.cpp 3
|
||||
|
||||
Note that the startup function will run at the end of the QCoreApplication constructor,
|
||||
before any GUI initialization. If GUI code is required in the function,
|
||||
use a timer (or a queued invocation) to perform the initialization later on,
|
||||
from the event loop.
|
||||
|
||||
If QCoreApplication is deleted and another QCoreApplication is created,
|
||||
the startup function will be invoked again.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void qAddPostRoutine(QtCleanUpFunction ptr)
|
||||
\relates QCoreApplication
|
||||
|
@ -220,12 +220,20 @@ public: \
|
||||
{ return QCoreApplication::translate(#context, sourceText, disambiguation, n); } \
|
||||
private:
|
||||
|
||||
typedef void (*QtStartUpFunction)();
|
||||
typedef void (*QtCleanUpFunction)();
|
||||
|
||||
Q_CORE_EXPORT void qAddPreRoutine(QtStartUpFunction);
|
||||
Q_CORE_EXPORT void qAddPostRoutine(QtCleanUpFunction);
|
||||
Q_CORE_EXPORT void qRemovePostRoutine(QtCleanUpFunction);
|
||||
Q_CORE_EXPORT QString qAppName(); // get application name
|
||||
|
||||
#define Q_COREAPP_STARTUP_FUNCTION(AFUNC) \
|
||||
static void AFUNC ## _ctor_function() { \
|
||||
qAddPreRoutine(AFUNC); \
|
||||
} \
|
||||
Q_CONSTRUCTOR_FUNCTION(AFUNC ## _ctor_function)
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM)
|
||||
Q_CORE_EXPORT QString decodeMSG(const MSG &);
|
||||
Q_CORE_EXPORT QDebug operator<<(QDebug, const MSG &);
|
||||
|
@ -55,6 +55,8 @@ private slots:
|
||||
void checkptr();
|
||||
void qstaticassert();
|
||||
void qConstructorFunction();
|
||||
void qCoreAppStartupFunction();
|
||||
void qCoreAppStartupFunctionRestart();
|
||||
void isEnum();
|
||||
void qAlignOf();
|
||||
};
|
||||
@ -303,6 +305,33 @@ void tst_QGlobal::qConstructorFunction()
|
||||
QCOMPARE(qConstructorFunctionValue, 123);
|
||||
}
|
||||
|
||||
static int qStartupFunctionValue;
|
||||
static void myStartupFunc()
|
||||
{
|
||||
Q_ASSERT(QCoreApplication::instance());
|
||||
if (QCoreApplication::instance())
|
||||
qStartupFunctionValue += 124;
|
||||
}
|
||||
|
||||
Q_COREAPP_STARTUP_FUNCTION(myStartupFunc)
|
||||
|
||||
void tst_QGlobal::qCoreAppStartupFunction()
|
||||
{
|
||||
QCOMPARE(qStartupFunctionValue, 0);
|
||||
int argc = 1;
|
||||
char *argv[] = { const_cast<char*>("tst_qglobal") };
|
||||
QCoreApplication app(argc, argv);
|
||||
QCOMPARE(qStartupFunctionValue, 124);
|
||||
}
|
||||
|
||||
void tst_QGlobal::qCoreAppStartupFunctionRestart()
|
||||
{
|
||||
qStartupFunctionValue = 0;
|
||||
qCoreAppStartupFunction();
|
||||
qStartupFunctionValue = 0;
|
||||
qCoreAppStartupFunction();
|
||||
}
|
||||
|
||||
struct isEnum_A {
|
||||
int n_;
|
||||
};
|
||||
@ -532,5 +561,5 @@ void tst_QGlobal::qAlignOf()
|
||||
#undef TEST_AlignOf_RValueRef
|
||||
#undef TEST_AlignOf_impl
|
||||
|
||||
QTEST_MAIN(tst_QGlobal)
|
||||
QTEST_APPLESS_MAIN(tst_QGlobal)
|
||||
#include "tst_qglobal.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user