diff options
Diffstat (limited to 'cppuhelper')
-rw-r--r-- | cppuhelper/source/servicemanager.cxx | 97 | ||||
-rw-r--r-- | cppuhelper/source/servicemanager.hxx | 19 |
2 files changed, 88 insertions, 28 deletions
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx index f06405f7794b..fe9ef7dbd2b4 100644 --- a/cppuhelper/source/servicemanager.cxx +++ b/cppuhelper/source/servicemanager.cxx @@ -327,6 +327,7 @@ void Parser::handleComponent() { void Parser::handleImplementation() { OUString attrName; OUString attrConstructor; + bool attrSingleInstance = false; xmlreader::Span name; int nsId; while (reader_.nextAttribute(&nsId, &name)) { @@ -366,6 +367,19 @@ void Parser::handleImplementation() { + ": <implementation> has \"constructor\" attribute but" " <component> has no \"environment\" attribute"); } + } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE + && name.equals(RTL_CONSTASCII_STRINGPARAM("single-instance"))) + { + if (attrSingleInstance) { + throw css::registry::InvalidRegistryException( + reader_.getUrl() + + ": <implementation> has multiple \"single-instance\" attributes"); + } + if (!reader_.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("true"))) { + throw css::registry::InvalidRegistryException( + reader_.getUrl() + ": <implementation> has bad \"single-instance\" attribute"); + } + attrSingleInstance = true; } else { throw css::registry::InvalidRegistryException( reader_.getUrl() + ": unexpected element attribute \"" @@ -380,7 +394,7 @@ void Parser::handleImplementation() { implementation_ = std::make_shared<cppuhelper::ServiceManager::Data::Implementation>( attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor, - attrPrefix_, alienContext_, reader_.getUrl()); + attrPrefix_, attrSingleInstance, alienContext_, reader_.getUrl()); if (!data_->namedImplementations.emplace(attrName, implementation_). second) { @@ -647,28 +661,62 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance( bool singletonRequest) { css::uno::Reference<css::uno::XInterface> inst; + if (isSingleInstance) { + osl::MutexGuard g(mutex); + if (!singleInstance.is()) { + singleInstance = doCreateInstance(context); + } + inst = singleInstance; + } else { + inst = doCreateInstance(context); + } + updateDisposeInstance(singletonRequest, inst); + return inst; +} + +css::uno::Reference<css::uno::XInterface> +cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments( + css::uno::Reference<css::uno::XComponentContext> const & context, + bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments) +{ + css::uno::Reference<css::uno::XInterface> inst; + if (isSingleInstance) { + osl::MutexGuard g(mutex); + if (!singleInstance.is()) { + singleInstance = doCreateInstanceWithArguments(context, arguments); + } + inst = singleInstance; + } else { + inst = doCreateInstanceWithArguments(context, arguments); + } + updateDisposeInstance(singletonRequest, inst); + return inst; +} + +css::uno::Reference<css::uno::XInterface> +cppuhelper::ServiceManager::Data::Implementation::doCreateInstance( + css::uno::Reference<css::uno::XComponentContext> const & context) +{ if (constructorFn) { - inst.set( + return css::uno::Reference<css::uno::XInterface>( constructorFn(context.get(), css::uno::Sequence<css::uno::Any>()), SAL_NO_ACQUIRE); } else if (factory1.is()) { - inst = factory1->createInstanceWithContext(context); + return factory1->createInstanceWithContext(context); } else { assert(factory2.is()); - inst = factory2->createInstance(); + return factory2->createInstance(); } - updateDisposeSingleton(singletonRequest, inst); - return inst; } css::uno::Reference<css::uno::XInterface> -cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments( +cppuhelper::ServiceManager::Data::Implementation::doCreateInstanceWithArguments( css::uno::Reference<css::uno::XComponentContext> const & context, - bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments) + css::uno::Sequence<css::uno::Any> const & arguments) { - css::uno::Reference<css::uno::XInterface> inst; if (constructorFn) { - inst.set(constructorFn(context.get(), arguments), SAL_NO_ACQUIRE); + css::uno::Reference<css::uno::XInterface> inst( + constructorFn(context.get(), arguments), SAL_NO_ACQUIRE); //HACK: The constructor will either observe arguments and return inst // that does not implement XInitialization (or null), or ignore // arguments and return inst that implements XInitialization; this @@ -679,18 +727,17 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments( if (init.is()) { init->initialize(arguments); } + return inst; } else if (factory1.is()) { - inst = factory1->createInstanceWithArgumentsAndContext( + return factory1->createInstanceWithArgumentsAndContext( arguments, context); } else { assert(factory2.is()); - inst = factory2->createInstanceWithArguments(arguments); + return factory2->createInstanceWithArguments(arguments); } - updateDisposeSingleton(singletonRequest, inst); - return inst; } -void cppuhelper::ServiceManager::Data::Implementation::updateDisposeSingleton( +void cppuhelper::ServiceManager::Data::Implementation::updateDisposeInstance( bool singletonRequest, css::uno::Reference<css::uno::XInterface> const & instance) { @@ -702,15 +749,15 @@ void cppuhelper::ServiceManager::Data::Implementation::updateDisposeSingleton( // the implementation hands out different instances): if (singletonRequest) { osl::MutexGuard g(mutex); - disposeSingleton.clear(); + disposeInstance.clear(); dispose = false; - } else if (!singletons.empty()) { + } else if (shallDispose()) { css::uno::Reference<css::lang::XComponent> comp( instance, css::uno::UNO_QUERY); if (comp.is()) { osl::MutexGuard g(mutex); if (dispose) { - disposeSingleton = comp; + disposeInstance = comp; } } } @@ -840,20 +887,20 @@ void cppuhelper::ServiceManager::disposing() { for (const auto& rEntry : data_.namedImplementations) { assert(rEntry.second); - if (!rEntry.second->singletons.empty()) { + if (rEntry.second->shallDispose()) { osl::MutexGuard g2(rEntry.second->mutex); - if (rEntry.second->disposeSingleton.is()) { - sngls.push_back(rEntry.second->disposeSingleton); + if (rEntry.second->disposeInstance.is()) { + sngls.push_back(rEntry.second->disposeInstance); } } } for (const auto& rEntry : data_.dynamicImplementations) { assert(rEntry.second); - if (!rEntry.second->singletons.empty()) { + if (rEntry.second->shallDispose()) { osl::MutexGuard g2(rEntry.second->mutex); - if (rEntry.second->disposeSingleton.is()) { - sngls.push_back(rEntry.second->disposeSingleton); + if (rEntry.second->disposeInstance.is()) { + sngls.push_back(rEntry.second->disposeInstance); } } if (rEntry.second->component.is()) { @@ -1395,7 +1442,7 @@ bool cppuhelper::ServiceManager::readLegacyRdbFile(OUString const & uri) { std::shared_ptr< Data::Implementation > impl = std::make_shared<Data::Implementation>( name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"), - readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "", + readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "", false, css::uno::Reference< css::uno::XComponentContext >(), uri); if (!data_.namedImplementations.emplace(name, impl).second) { diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx index 9a7cac513402..24a7e56a4ba9 100644 --- a/cppuhelper/source/servicemanager.hxx +++ b/cppuhelper/source/servicemanager.hxx @@ -74,11 +74,13 @@ public: OUString const & theUri, OUString const & theEnvironment, OUString const & theConstructorName, OUString const & thePrefix, + bool theIsSingleInstance, css::uno::Reference< css::uno::XComponentContext > const & theAlienContext, OUString const & theRdbFile): name(theName), loader(theLoader), uri(theUri), environment(theEnvironment), constructorName(theConstructorName), prefix(thePrefix), + isSingleInstance(theIsSingleInstance), alienContext(theAlienContext), rdbFile(theRdbFile), constructorFn(nullptr), status(STATUS_NEW), dispose(true) {} @@ -91,7 +93,7 @@ public: theFactory2, css::uno::Reference< css::lang::XComponent > const & theComponent): - name(theName), constructorFn(nullptr), + name(theName), isSingleInstance(false), constructorFn(nullptr), factory1(theFactory1), factory2(theFactory2), component(theComponent), status(STATUS_LOADED), dispose(true) { assert(theFactory1.is() || theFactory2.is()); } @@ -111,6 +113,8 @@ public: bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments); + bool shallDispose() const { return isSingleInstance || !singletons.empty(); } + enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED }; // Logically, exactly one of constructorFn, factory1, factory2 should @@ -130,6 +134,7 @@ public: OUString environment; OUString constructorName; OUString prefix; + bool isSingleInstance; css::uno::Reference< css::uno::XComponentContext > alienContext; OUString rdbFile; std::vector< OUString > services; @@ -141,11 +146,19 @@ public: Status status; osl::Mutex mutex; - css::uno::Reference< css::lang::XComponent > disposeSingleton; + css::uno::Reference<css::uno::XInterface> singleInstance; + css::uno::Reference< css::lang::XComponent > disposeInstance; bool dispose; private: - void updateDisposeSingleton( + css::uno::Reference<css::uno::XInterface> doCreateInstance( + css::uno::Reference<css::uno::XComponentContext> const & context); + + css::uno::Reference<css::uno::XInterface> doCreateInstanceWithArguments( + css::uno::Reference<css::uno::XComponentContext> const & context, + css::uno::Sequence<css::uno::Any> const & arguments); + + void updateDisposeInstance( bool singletonRequest, css::uno::Reference<css::uno::XInterface> const & instance); }; |