QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) : mainContext(context) { #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32 if (qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")) { static QBasicMutex mutex; QMutexLocker locker(&mutex); if (!g_thread_supported()) g_thread_init(NULL); } #endif if (mainContext) { g_main_context_ref(mainContext); } else { QCoreApplication *app = QCoreApplication::instance(); if (app && QThread::currentThread() == app->thread()) { mainContext = g_main_context_default(); g_main_context_ref(mainContext); } else { mainContext = g_main_context_new(); } } #if GLIB_CHECK_VERSION (2, 22, 0) g_main_context_push_thread_default (mainContext); #endif // setup post event source postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs, sizeof(GPostEventSource))); postEventSource->serialNumber.store(1); postEventSource->d = this; g_source_set_can_recurse(&postEventSource->source, true); g_source_attach(&postEventSource->source, mainContext); // setup socketNotifierSource socketNotifierSource = reinterpret_cast<GSocketNotifierSource *>(g_source_new(&socketNotifierSourceFuncs, sizeof(GSocketNotifierSource))); (void) new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>(); g_source_set_can_recurse(&socketNotifierSource->source, true); g_source_attach(&socketNotifierSource->source, mainContext); // setup normal and idle timer sources timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs, sizeof(GTimerSource))); (void) new (&timerSource->timerList) QTimerInfoList(); timerSource->processEventsFlags = QEventLoop::AllEvents; timerSource->runWithIdlePriority = false; g_source_set_can_recurse(&timerSource->source, true); g_source_attach(&timerSource->source, mainContext); idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs, sizeof(GIdleTimerSource))); idleTimerSource->timerSource = timerSource; g_source_set_can_recurse(&idleTimerSource->source, true); g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE); g_source_attach(&idleTimerSource->source, mainContext); }
/*! Enters the main event loop and waits until exit() is called. Returns the value that was passed to exit(). If \a flags are specified, only events of the types allowed by the \a flags will be processed. It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. Generally speaking, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets use their own local event loop. To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More sophisticated idle processing schemes can be achieved using processEvents(). \sa QApplication::quit(), exit(), processEvents() */ int QEventLoop::exec(ProcessEventsFlags flags) { Q_D(QEventLoop); //we need to protect from race condition with QThread::exit QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex); if (d->threadData->quitNow) return -1; if (d->inExec) { qWarning("QEventLoop::exec: instance %p has already called exec()", this); return -1; } d->inExec = true; d->exit = false; ++d->threadData->loopLevel; d->threadData->eventLoops.push(this); locker.unlock(); // remove posted quit events when entering a new event loop QCoreApplication *app = QCoreApplication::instance(); if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); #if defined(QT_NO_EXCEPTIONS) while (!d->exit) processEvents(flags | WaitForMoreEvents | EventLoopExec); #else try { while (!d->exit) processEvents(flags | WaitForMoreEvents | EventLoopExec); } catch (...) { qWarning("Qt has caught an exception thrown from an event handler. Throwing\n" "exceptions from an event handler is not supported in Qt. You must\n" "reimplement QApplication::notify() and catch all exceptions there.\n"); // copied from below locker.relock(); QEventLoop *eventLoop = d->threadData->eventLoops.pop(); Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); Q_UNUSED(eventLoop); // --release warning d->inExec = false; --d->threadData->loopLevel; throw; } #endif // copied above locker.relock(); QEventLoop *eventLoop = d->threadData->eventLoops.pop(); Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); Q_UNUSED(eventLoop); // --release warning d->inExec = false; --d->threadData->loopLevel; return d->returnCode; }
/*! Enters the main event loop and waits until exit() is called. Returns the value that was passed to exit(). If \a flags are specified, only events of the types allowed by the \a flags will be processed. It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. Generally speaking, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets use their own local event loop. To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More sophisticated idle processing schemes can be achieved using processEvents(). \sa QCoreApplication::quit(), exit(), processEvents() */ int QEventLoop::exec(ProcessEventsFlags flags) { Q_D(QEventLoop); //we need to protect from race condition with QThread::exit QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex); if (d->threadData->quitNow) return -1; if (d->inExec) { qWarning("QEventLoop::exec: instance %p has already called exec()", this); return -1; } struct LoopReference { QEventLoopPrivate *d; QMutexLocker &locker; bool exceptionCaught; LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true) { d->inExec = true; d->exit.storeRelease(false); ++d->threadData->loopLevel; d->threadData->eventLoops.push(d->q_func()); locker.unlock(); } ~LoopReference() { if (exceptionCaught) { qWarning("Qt has caught an exception thrown from an event handler. Throwing\n" "exceptions from an event handler is not supported in Qt.\n" "You must not let any exception whatsoever propagate through Qt code.\n" "If that is not possible, in Qt 5 you must at least reimplement\n" "QCoreApplication::notify() and catch all exceptions there.\n"); } locker.relock(); QEventLoop *eventLoop = d->threadData->eventLoops.pop(); Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error"); Q_UNUSED(eventLoop); // --release warning d->inExec = false; --d->threadData->loopLevel; } }; LoopReference ref(d, locker); // remove posted quit events when entering a new event loop QCoreApplication *app = QCoreApplication::instance(); if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); while (!d->exit.loadAcquire()) processEvents(flags | WaitForMoreEvents | EventLoopExec); ref.exceptionCaught = false; return d->returnCode.load(); }
/*! Enters the main event loop and waits until exit() is called. Returns the value that was passed to exit(). If \a flags are specified, only events of the types allowed by the \a flags will be processed. It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. Generally speaking, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets use their own local event loop. To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More sophisticated idle processing schemes can be achieved using processEvents(). \sa QApplication::quit(), exit(), processEvents() */ int QEventLoop::exec(ProcessEventsFlags flags) { Q_D(QEventLoop); if (d->threadData->quitNow) return -1; if (d->inExec) { qWarning("QEventLoop::exec: instance %p has already called exec()", this); return -1; } d->inExec = true; d->exit = false; ++d->threadData->loopLevel; d->threadData->eventLoops.push(this); // remove posted quit events when entering a new event loop QCoreApplication *app = QCoreApplication::instance(); if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); #if defined(QT_NO_EXCEPTIONS) while (!d->exit) { //printf("** qeventloop() 1 right before handle_events\n"); processEvents(flags | WaitForMoreEvents | EventLoopExec); } #else try { while (!d->exit) { processEvents(flags | WaitForMoreEvents | EventLoopExec); } } catch (...) { qWarning("Qt has caught an exception thrown from an event handler. Throwing\n" "exceptions from an event handler is not supported in Qt. You must\n" "reimplement QApplication::notify() and catch all exceptions there.\n"); // copied from below QEventLoop *eventLoop = d->threadData->eventLoops.pop(); Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); Q_UNUSED(eventLoop); // --release warning d->inExec = false; --d->threadData->loopLevel; throw; } #endif // copied above QEventLoop *eventLoop = d->threadData->eventLoops.pop(); Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); Q_UNUSED(eventLoop); // --release warning d->inExec = false; --d->threadData->loopLevel; return d->returnCode; }
inline QDBusDefaultConnection(BusType type, const char *name) : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name) { // make sure this connection is running on the main thread QCoreApplication *instance = QCoreApplication::instance(); if (!instance) { qWarning("QDBusConnection: %s D-Bus connection created before QCoreApplication. Application may misbehave.", type == SessionBus ? "session" : type == SystemBus ? "system" : "generic"); } else if (QDBusConnectionPrivate::d(*this)) { QDBusConnectionPrivate::d(*this)->moveToThread(instance->thread()); } }
QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) : mainContext(context) { if (qgetenv("QT_NO_THREADED_GLIB").isEmpty()) { static int dummyValue = 0; // only used for its address QMutexLocker locker(QMutexPool::instance()->get(&dummyValue)); if (!g_thread_supported()) g_thread_init(NULL); } if (mainContext) { g_main_context_ref(mainContext); } else { QCoreApplication *app = QCoreApplication::instance(); if (app && QThread::currentThread() == app->thread()) { mainContext = g_main_context_default(); g_main_context_ref(mainContext); } else { mainContext = g_main_context_new(); } } // setup post event source postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs, sizeof(GPostEventSource))); postEventSource->serialNumber = 1; g_source_set_can_recurse(&postEventSource->source, true); g_source_attach(&postEventSource->source, mainContext); // setup socketNotifierSource socketNotifierSource = reinterpret_cast<GSocketNotifierSource *>(g_source_new(&socketNotifierSourceFuncs, sizeof(GSocketNotifierSource))); (void) new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>(); g_source_set_can_recurse(&socketNotifierSource->source, true); g_source_attach(&socketNotifierSource->source, mainContext); // setup normal and idle timer sources timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs, sizeof(GTimerSource))); (void) new (&timerSource->timerList) QTimerInfoList(); timerSource->processEventsFlags = QEventLoop::AllEvents; timerSource->runWithIdlePriority = false; g_source_set_can_recurse(&timerSource->source, true); g_source_attach(&timerSource->source, mainContext); idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs, sizeof(GIdleTimerSource))); idleTimerSource->timerSource = timerSource; g_source_set_can_recurse(&idleTimerSource->source, true); g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE); g_source_attach(&idleTimerSource->source, mainContext); }
void QDnsLookupThreadPool::start(QRunnable *runnable) { // Ensure threads complete at application destruction. if (!signalsConnected) { QMutexLocker signalsLocker(&signalsMutex); if (!signalsConnected) { QCoreApplication *app = QCoreApplication::instance(); if (!app) { qWarning("QDnsLookup requires a QCoreApplication"); delete runnable; return; } moveToThread(app->thread()); connect(app, SIGNAL(destroyed()), SLOT(_q_applicationDestroyed()), Qt::DirectConnection); signalsConnected = true; } } QThreadPool::start(runnable); }
void QWebEngine::initialize() { QCoreApplication *app = QCoreApplication::instance(); if (!app) { qFatal("QWebEngine(Widgets)::initialize() must be called after the construction of the application object."); return; } if (app->thread() != QThread::currentThread()) { qFatal("QWebEngine(Widgets)::initialize() must be called from the Qt gui thread."); return; } if (shareContext) return; shareContext = new QOpenGLContext; shareContext->create(); qAddPostRoutine(deleteShareContext); #if (QT_VERSION < QT_VERSION_CHECK(5, 3, 0)) QSGContext::setSharedOpenGLContext(shareContext); #else QOpenGLContextPrivate::setGlobalShareContext(shareContext); #endif }
QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) : mainContext(context) { if (qgetenv("QT_NO_THREADED_GLIB").isEmpty()) { static int dummyValue = 0; // only used for its address QMutexLocker locker(QMutexPool::instance()->get(&dummyValue)); if (!g_thread_supported()) g_thread_init(NULL); } if (mainContext) { g_main_context_ref(mainContext); } else { QCoreApplication *app = QCoreApplication::instance(); if (app && QThread::currentThread() == app->thread()) { mainContext = g_main_context_default(); g_main_context_ref(mainContext); } else { mainContext = g_main_context_new(); } } #if GLIB_CHECK_VERSION (2, 22, 0) g_main_context_push_thread_default (mainContext); #endif // setup post event source postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs, sizeof(GPostEventSource))); postEventSource->serialNumber = 1; postEventSource->d = this; g_source_set_can_recurse(&postEventSource->source, true); g_source_attach(&postEventSource->source, mainContext); // setup socketNotifierSource socketNotifierSource = reinterpret_cast<GSocketNotifierSource *>(g_source_new(&socketNotifierSourceFuncs, sizeof(GSocketNotifierSource))); (void) new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>(); g_source_set_can_recurse(&socketNotifierSource->source, true); g_source_attach(&socketNotifierSource->source, mainContext); // setup normal and idle timer sources timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs, sizeof(GTimerSource))); (void) new (&timerSource->timerList) QTimerInfoList(); timerSource->processEventsFlags = QEventLoop::AllEvents; timerSource->runWithIdlePriority = false; g_source_set_can_recurse(&timerSource->source, true); #ifdef QT_WEBOS #ifdef QT_USE_TIMERFD int timerfd = ::timerfd_create(CLOCK_MONOTONIC, 0); timerSource->timerPollFd.fd = timerfd; if (timerfd == -1) { qErrnoWarning(errno, "timerfd_create failed"); } else { // TFD_NONBLOCK is not always defined, so use fcntl to set non-blocking long flags = ::fcntl(timerfd, F_GETFL); if (flags == -1) { qErrnoWarning(errno, "fcntl F_GETFL failed"); } else { if (::fcntl(timerfd, F_SETFL, flags | O_NONBLOCK) == -1) { qErrnoWarning(errno, "fcntl F_SETFL failed"); } } timerSource->timerPollFd.events = G_IO_IN; g_source_add_poll(&timerSource->source, &timerSource->timerPollFd); } #endif #endif // QT_WEBOS g_source_attach(&timerSource->source, mainContext); idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs, sizeof(GIdleTimerSource))); idleTimerSource->timerSource = timerSource; g_source_set_can_recurse(&idleTimerSource->source, true); g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE); #ifndef QT_WEBOS g_source_attach(&idleTimerSource->source, mainContext); #endif // QT_WEBOS }
//--------------------------------------------------------------------------------------------------------------------- inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { // Why on earth didn't Qt want to make failed signal/slot connections qWarning? if ((type == QtDebugMsg) && msg.contains("::connect")) { type = QtWarningMsg; } // this is another one that doesn't make sense as just a debug message. pretty serious // sign of a problem // http://www.developer.nokia.com/Community/Wiki/QPainter::begin:Paint_device_returned_engine_%3D%3D_0_(Known_Issue) if ((type == QtDebugMsg) && msg.contains("QPainter::begin") && msg.contains("Paint device returned engine")) { type = QtWarningMsg; } // This qWarning about "Cowardly refusing to send clipboard message to hung application..." // is something that can easily happen if you are debugging and the application is paused. // As it is so common, not worth popping up a dialog. if ((type == QtWarningMsg) && QString(msg).contains("QClipboard::event") && QString(msg).contains("Cowardly refusing")) { type = QtDebugMsg; } // only the GUI thread should display message boxes. If you are // writing a multithreaded application and the error happens on // a non-GUI thread, you'll have to queue the message to the GUI QCoreApplication *instance = QCoreApplication::instance(); const bool isGuiThread = instance && (QThread::currentThread() == instance->thread()); if (isGuiThread) { QByteArray localMsg = msg.toLocal8Bit(); QMessageBox messageBox; switch (type) { case QtDebugMsg: fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); return; case QtWarningMsg: messageBox.setIcon(QMessageBox::Warning); messageBox.setInformativeText(msg); messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtCriticalMsg: messageBox.setIcon(QMessageBox::Critical); messageBox.setInformativeText(msg); messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtFatalMsg: messageBox.setIcon(QMessageBox::Critical); messageBox.setInformativeText(msg); messageBox.setStandardButtons(QMessageBox::Cancel); fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; default: break; } const int ret = messageBox.exec(); if (ret == QMessageBox::Cancel) { abort(); } } else { if (type != QtDebugMsg) { abort(); // be NOISY unless overridden! } } }
int main(int argc, char** argv) { SettingsImplementation settings; int effective_argc = argc; std::string path_to_bin(argv[0]); if (!settings.knows("path_to_bin")) { settings.addTemporary(csapex::param::factory::declareFileInputPath("path_to_bin", path_to_bin)); } else { settings.set("path_to_bin", path_to_bin); } po::options_description desc("Allowed options"); desc.add_options()("help", "show help message")("host", po::value<std::string>()->default_value("localhost"), "Host")("port", po::value<int>()->default_value(42123), "Port"); po::positional_options_description p; std::shared_ptr<ExceptionHandler> handler; // filters all qt parameters from argv std::shared_ptr<GuiExceptionHandler> h(new GuiExceptionHandler(false)); handler = h; QCoreApplication* app = new CsApexGuiApp(effective_argc, argv, *handler); h->moveToThread(app->thread()); // filters ros remappings std::vector<std::string> remapping_args; std::vector<std::string> rest_args; for (int i = 1; i < effective_argc; ++i) { std::string arg(argv[i]); if (arg.find(":=") != std::string::npos) { remapping_args.push_back(arg); } else { rest_args.push_back(arg); } } // now check for remaining parameters po::variables_map vm; std::vector<std::string> additional_args; try { po::parsed_options parsed = po::command_line_parser(rest_args).options(desc).positional(p).run(); po::store(parsed, vm); po::notify(vm); additional_args = po::collect_unrecognized(parsed.options, po::include_positional); } catch (const std::exception& e) { std::cerr << "cannot parse parameters: " << e.what() << std::endl; return 4; } // add ros remappings additional_args.insert(additional_args.end(), remapping_args.begin(), remapping_args.end()); // display help? if (vm.count("help")) { std::cerr << desc << std::endl; return 1; } // server settings settings.set("host", vm["host"].as<std::string>()); settings.set("port", vm["port"].as<int>()); // start the app Main m(app, settings, *handler); try { return m.run(); } catch (const csapex::Failure& af) { std::cerr << af.what() << std::endl; return 42; } }