//---------------------------------------------------------------------------- ctkPluginFrameworkEvent ctkPluginFramework::waitForStop(unsigned long timeout) { Q_D(ctkPluginFramework); ctkPluginPrivate::Locker sync(&d->lock); // Already stopped? if ((d->state & (INSTALLED | RESOLVED)) == 0) { d->stopEvent.isNull = true; d->lock.wait(timeout ? timeout : ULONG_MAX); if (d->stopEvent.isNull) { return ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::FRAMEWORK_WAIT_TIMEDOUT, this->d_func()->q_func()); } } else if (d->stopEvent.isNull) { // Return this if stop or update have not been called and framework is stopped. d->stopEvent.isNull = false; d->stopEvent.type = ctkPluginFrameworkEvent::FRAMEWORK_STOPPED; } return d->stopEvent.isNull ? ctkPluginFrameworkEvent() : ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::FRAMEWORK_STOPPED, this->d_func()->q_func()); }
//---------------------------------------------------------------------------- void ctkPluginFrameworkPrivate::shutdown(bool restart) { Locker sync(&lock); bool wasActive = false; switch (state) { case ctkPlugin::INSTALLED: case ctkPlugin::RESOLVED: shutdownDone_unlocked(false); break; case ctkPlugin::ACTIVE: wasActive = true; // Fall through case ctkPlugin::STARTING: if (shuttingDown.fetchAndAddOrdered(0) == 0) { try { const bool wa = wasActive; shuttingDown.fetchAndStoreOrdered(1); QtConcurrent::run(this, &ctkPluginFrameworkPrivate::shutdown0, restart, wa); } catch (const std::exception& e) { systemShuttingdownDone(ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::PLUGIN_ERROR, this->q_func(), e)); } } break; case ctkPlugin::STOPPING: // Shutdown already inprogress, fall through case ctkPlugin::UNINSTALLED: break; } }
//---------------------------------------------------------------------------- void ctkPluginFramework::start(const ctkPlugin::StartOptions& options) { Q_UNUSED(options); Q_D(ctkPluginFramework); QStringList pluginsToStart; { ctkPluginPrivate::Locker sync(&d->lock); d->waitOnOperation(&d->lock, "ctkPluginFramework::start", true); switch (d->state) { case INSTALLED: case RESOLVED: d->init(); case STARTING: d->operation.fetchAndStoreOrdered(ctkPluginPrivate::ACTIVATING); break; case ACTIVE: return; default: throw ctkIllegalStateException("INTERNAL ERROR, Illegal state"); } pluginsToStart = d->fwCtx->storage->getStartOnLaunchPlugins(); } // Start plugins according to their autostart setting. QStringListIterator i(pluginsToStart); while (i.hasNext()) { QSharedPointer<ctkPlugin> plugin = d->fwCtx->plugins->getPlugin(i.next()); try { const int autostartSetting = plugin->d_func()->archive->getAutostartSetting(); // Launch must not change the autostart setting of a plugin StartOptions option = ctkPlugin::START_TRANSIENT; if (ctkPlugin::START_ACTIVATION_POLICY == autostartSetting) { // Transient start according to the plugins activation policy. option |= ctkPlugin::START_ACTIVATION_POLICY; } plugin->start(option); } catch (const ctkPluginException& pe) { d->fwCtx->listeners.frameworkError(plugin, pe); } } { ctkPluginPrivate::Locker sync(&d->lock); d->state = ACTIVE; d->operation = ctkPluginPrivate::IDLE; d->lock.wakeAll(); d->fwCtx->listeners.emitFrameworkEvent( ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::FRAMEWORK_STARTED, this->d_func()->q_func())); } }
void ctkPluginFramework::start(const ctkPlugin::StartOptions& options) { Q_UNUSED(options); Q_D(ctkPluginFramework); QStringList pluginsToStart; { QMutexLocker sync(&d->lock); // TODO: parallel start //waitOnActivation(lock, "ctkPluginFramework::start", true); switch (d->state) { case INSTALLED: case RESOLVED: d->init(); case STARTING: d->activating = true; break; case ACTIVE: return; default: throw std::logic_error("INTERNAL ERROR, Illegal state"); } pluginsToStart = d->fwCtx->storage.getStartOnLaunchPlugins(); } // Start plugins according to their autostart setting. QStringListIterator i(pluginsToStart); while (i.hasNext()) { ctkPlugin* plugin = d->fwCtx->plugins->getPlugin(i.next()); try { const int autostartSetting = plugin->d_func()->archive->getAutostartSetting(); // Launch must not change the autostart setting of a plugin StartOptions option = ctkPlugin::START_TRANSIENT; if (ctkPlugin::START_ACTIVATION_POLICY == autostartSetting) { // Transient start according to the plugins activation policy. option |= ctkPlugin::START_ACTIVATION_POLICY; } plugin->start(option); } catch (const ctkPluginException& pe) { d->fwCtx->listeners.frameworkError(plugin, pe); } } { QMutexLocker sync(&d->lock); d->state = ACTIVE; d->activating = false; d->fwCtx->listeners.emitFrameworkEvent( ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::STARTED, this)); } }
//---------------------------------------------------------------------------- void ctkPluginFrameworkPrivate::shutdown0(bool restart, bool wasActive) { try { { Locker sync(&lock); waitOnOperation(&lock, QString("Framework::") + (restart ? "update" : "stop"), true); operation = DEACTIVATING; state = ctkPlugin::STOPPING; } fwCtx->listeners.emitPluginChanged( ctkPluginEvent(ctkPluginEvent::STOPPING, this->q_func())); if (wasActive) { stopAllPlugins(); } { Locker sync(&lock); fwCtx->uninit(); shuttingDown.fetchAndStoreOrdered(0); shutdownDone_unlocked(restart); } if (restart) { if (wasActive) { q_func().toStrongRef()->start(); } else { init(); } } } catch (const ctkException& e) { shuttingDown.fetchAndStoreOrdered(0); systemShuttingdownDone(ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::PLUGIN_ERROR, this->q_func(), e)); } }
//---------------------------------------------------------------------------- void ctkPluginFrameworkPrivate::shutdownDone_unlocked(bool restart) { ctkPluginFrameworkEvent::Type t = restart ? ctkPluginFrameworkEvent::FRAMEWORK_STOPPED_UPDATE : ctkPluginFrameworkEvent::FRAMEWORK_STOPPED; systemShuttingdownDone_unlocked(ctkPluginFrameworkEvent(t, this->q_func())); }
void ctkPluginFrameworkListeners::frameworkError(ctkPlugin* p, const std::exception& e) { emit frameworkEvent(ctkPluginFrameworkEvent(ctkPluginFrameworkEvent::ERROR, p, e)); }