void ctkServiceRegistration::setProperties(const ServiceProperties& props) { Q_D(ctkServiceRegistration); if (!d) throw std::logic_error("ctkServiceRegistration object invalid"); QMutexLocker lock(&d->eventLock); QSet<ctkServiceSlotEntry> before; // TBD, optimize the locking of services { QMutexLocker lock2(&d->plugin->fwCtx->globalFwLock); QMutexLocker lock3(&d->propsLock); if (d->available) { // NYI! Optimize the MODIFIED_ENDMATCH code int old_rank = d->properties.value(ctkPluginConstants::SERVICE_RANKING).toInt(); before = d->plugin->fwCtx->listeners.getMatchingServiceSlots(d->reference); QStringList classes = d->properties.value(ctkPluginConstants::OBJECTCLASS).toStringList(); qlonglong sid = d->properties.value(ctkPluginConstants::SERVICE_ID).toLongLong(); d->properties = ctkServices::createServiceProperties(props, classes, sid); int new_rank = d->properties.value(ctkPluginConstants::SERVICE_RANKING).toInt(); if (old_rank != new_rank) { d->plugin->fwCtx->services->updateServiceRegistrationOrder(*this, classes); } } else { throw std::logic_error("Service is unregistered"); } } d->plugin->fwCtx->listeners.serviceChanged( d->plugin->fwCtx->listeners.getMatchingServiceSlots(d->reference), ctkServiceEvent(ctkServiceEvent::MODIFIED, d->reference), before); d->plugin->fwCtx->listeners.serviceChanged( before, ctkServiceEvent(ctkServiceEvent::MODIFIED_ENDMATCH, d->reference)); }
ctkServiceRegistration ctkServices::registerService(ctkPluginPrivate* plugin, const QStringList& classes, QObject* service, const ctkDictionary& properties) { if (service == 0) { throw std::invalid_argument("Can't register 0 as a service"); } // Check if service implements claimed classes and that they exist. for (QStringListIterator i(classes); i.hasNext();) { QString cls = i.next(); if (cls.isEmpty()) { throw std::invalid_argument("Can't register as null class"); } if (!(qobject_cast<ctkServiceFactory*>(service))) { if (!checkServiceClass(service, cls)) { QString msg = QString("Service class %1 is not an instance of %2. Maybe you forgot the Q_INTERFACES macro in the service class.") .arg(service->metaObject()->className()).arg(cls); throw std::invalid_argument(msg.toStdString()); } } } ctkServiceRegistration res(plugin, service, createServiceProperties(properties, classes)); { QMutexLocker lock(&mutex); services.insert(res, classes); for (QStringListIterator i(classes); i.hasNext(); ) { QString currClass = i.next(); QList<ctkServiceRegistration>& s = classServices[currClass]; QList<ctkServiceRegistration>::iterator ip = std::lower_bound(s.begin(), s.end(), res, ServiceRegistrationComparator()); s.insert(ip, res); } } ctkServiceReference r = res.getReference(); plugin->fwCtx->listeners.serviceChanged( plugin->fwCtx->listeners.getMatchingServiceSlots(r), ctkServiceEvent(ctkServiceEvent::REGISTERED, r)); return res; }
void ctkServiceRegistration::unregister() { Q_D(ctkServiceRegistration); if (!d) throw std::logic_error("ctkServiceRegistration object invalid"); if (d->unregistering) return; // Silently ignore redundant unregistration. { QMutexLocker lock(&d->eventLock); if (d->unregistering) return; d->unregistering = true; if (d->available) { if (d->plugin) { d->plugin->fwCtx->services->removeServiceRegistration(*this); } } else { throw std::logic_error("Service is unregistered"); } } if (d->plugin) { d->plugin->fwCtx->listeners.serviceChanged( d->plugin->fwCtx->listeners.getMatchingServiceSlots(d->reference), ctkServiceEvent(ctkServiceEvent::UNREGISTERING, d->reference)); } { QMutexLocker lock(&d->eventLock); { QMutexLocker lock2(&d->propsLock); d->available = false; if (d->plugin) { for (QHashIterator<QSharedPointer<ctkPlugin>, QObject*> i(d->serviceInstances); i.hasNext();) { QObject* obj = i.next().value(); try { // NYI, don't call inside lock qobject_cast<ctkServiceFactory*>(d->service)->ungetService(i.key(), *this, obj); } catch (const std::exception& ue) { ctkPluginFrameworkEvent pfwEvent(ctkPluginFrameworkEvent::ERROR, d->plugin->q_func().data(), ue); d->plugin->fwCtx->listeners .emitFrameworkEvent(pfwEvent); } } } d->plugin = 0; d->dependents.clear(); d->service = 0; d->serviceInstances.clear();; d->unregistering = false; } } }