summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cppuhelper/source/servicemanager.cxx175
-rw-r--r--cppuhelper/source/servicemanager.hxx13
2 files changed, 76 insertions, 112 deletions
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index e6c31fc53302..973201d0f3c2 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -701,43 +701,19 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance(
css::uno::Reference<css::uno::XComponentContext> const & context,
bool singletonRequest)
{
- if (info->singletons.empty()) {
- assert(!singletonRequest);
- if (constructor != 0) {
- // the interface is already acquired, don't acquire here
- return css::uno::Reference<css::uno::XInterface>(
- (*constructor)(context.get(),
- css::uno::Sequence<css::uno::Any>()),
- SAL_NO_ACQUIRE);
- }
- if (factory1.is()) {
- return factory1->createInstanceWithContext(context);
- }
- assert(factory2.is());
- return factory2->createInstance();
+ css::uno::Reference<css::uno::XInterface> inst;
+ if (constructor != 0) {
+ inst.set(
+ (*constructor)(context.get(), css::uno::Sequence<css::uno::Any>()),
+ SAL_NO_ACQUIRE);
+ } else if (factory1.is()) {
+ inst = factory1->createInstanceWithContext(context);
} else {
- osl::MutexGuard g(mutex); //TODO: must be a non-recursive mutex
- if (singleton.is()) {
- if (singletonRequest) {
- dispose = false;
- }
- return singleton;
- }
- if (constructor != 0) {
- // the interface is already acquired, don't acquire here
- singleton.set(
- (*constructor)(context.get(),
- css::uno::Sequence<css::uno::Any>()),
- SAL_NO_ACQUIRE);
- } else if (factory1.is()) {
- singleton = factory1->createInstanceWithContext(context);
- } else {
- assert(factory2.is());
- singleton = factory2->createInstance();
- }
- dispose = singleton.is() && !singletonRequest;
- return singleton;
+ assert(factory2.is());
+ inst = factory2->createInstance();
}
+ updateDisposeSingleton(singletonRequest, inst);
+ return inst;
}
css::uno::Reference<css::uno::XInterface>
@@ -745,65 +721,54 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
css::uno::Reference<css::uno::XComponentContext> const & context,
bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
{
- if (info->singletons.empty()) {
- assert(!singletonRequest);
- if (constructor != 0) {
- // the interface is already acquired, don't acquire here
- css::uno::Reference<css::uno::XInterface> inst(
- (*constructor)(context.get(), arguments), SAL_NO_ACQUIRE);
-
- // HACK: The service can implement XInitialization too.
- // It should be removed when converting to constructor-based
- // initialization, but in case somebody forgets, be safe, and
- // call it anyway for the moment.
- css::uno::Reference<css::lang::XInitialization> xinit(
- inst, css::uno::UNO_QUERY);
- if (xinit.is()) {
- xinit->initialize(arguments);
- }
- return inst;
- }
- if (factory1.is()) {
- return factory1->createInstanceWithArgumentsAndContext(
- arguments, context);
+ css::uno::Reference<css::uno::XInterface> inst;
+ if (constructor != 0) {
+ inst.set((*constructor)(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
+ // should be removed again once XInitialization-based implementations
+ // have become rare:
+ css::uno::Reference<css::lang::XInitialization> init(
+ inst, css::uno::UNO_QUERY);
+ if (init.is()) {
+ init->initialize(arguments);
}
- assert(factory2.is());
- return factory2->createInstanceWithArguments(arguments);
+ return inst;
+ } else if (factory1.is()) {
+ inst = factory1->createInstanceWithArgumentsAndContext(
+ arguments, context);
} else {
- osl::MutexGuard g(mutex); //TODO: must be a non-recursive mutex
- if (singleton.is()) {
- SAL_WARN(
- "cppuhelper",
- "createInstanceWithArguments request for already instantiated"
- " singleton implementation " << info->name);
- if (singletonRequest) {
- dispose = false;
- }
- return singleton;
- }
- if (constructor != 0) {
- // the interface is already acquired, don't acquire here
- singleton.set(
- (*constructor)(context.get(), arguments), SAL_NO_ACQUIRE);
-
- // HACK: The service can implement XInitialization too.
- // It should be removed when converting to constructor-based
- // initialization, but in case somebody forgets, be safe, and
- // call it anyway for the moment.
- css::uno::Reference<css::lang::XInitialization> xinit(
- singleton, css::uno::UNO_QUERY);
- if (xinit.is()) {
- xinit->initialize(arguments);
+ assert(factory2.is());
+ inst = factory2->createInstanceWithArguments(arguments);
+ }
+ updateDisposeSingleton(singletonRequest, inst);
+ return inst;
+}
+
+void cppuhelper::ServiceManager::Data::Implementation::updateDisposeSingleton(
+ bool singletonRequest,
+ css::uno::Reference<css::uno::XInterface> const & instance)
+{
+ // This is an optimization, to only call dispose once (from the component
+ // context) on a singleton that is obtained both via the component context
+ // and via the service manager; however, there is a harmless race here that
+ // may cause two calls to dispose nevertheless (also, this calls dispose on
+ // at most one of the instances obtained via the service manager, in case
+ // the implementation hands out different instances):
+ if (singletonRequest) {
+ osl::MutexGuard g(mutex);
+ disposeSingleton.clear();
+ dispose = false;
+ } else if (!info->singletons.empty()) {
+ css::uno::Reference<css::lang::XComponent> comp(
+ instance, css::uno::UNO_QUERY);
+ if (comp.is()) {
+ osl::MutexGuard g(mutex);
+ if (dispose) {
+ disposeSingleton = comp;
}
- } else if (factory1.is()) {
- singleton = factory1->createInstanceWithArgumentsAndContext(
- arguments, context);
- } else {
- assert(factory2.is());
- singleton = factory2->createInstanceWithArguments(arguments);
}
- dispose = singleton.is() && !singletonRequest;
- return singleton;
}
}
@@ -938,7 +903,7 @@ void cppuhelper::ServiceManager::loadImplementation(
}
void cppuhelper::ServiceManager::disposing() {
- std::vector< css::uno::Reference<css::uno::XInterface> > sngls;
+ std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
std::vector< css::uno::Reference< css::lang::XComponent > > comps;
Data clear;
{
@@ -950,8 +915,8 @@ void cppuhelper::ServiceManager::disposing() {
assert(i->second.get() != 0);
if (!i->second->info->singletons.empty()) {
osl::MutexGuard g2(i->second->mutex);
- if (i->second->dispose) {
- sngls.push_back(i->second->singleton);
+ if (i->second->disposeSingleton.is()) {
+ sngls.push_back(i->second->disposeSingleton);
}
}
}
@@ -962,8 +927,8 @@ void cppuhelper::ServiceManager::disposing() {
assert(i->second.get() != 0);
if (!i->second->info->singletons.empty()) {
osl::MutexGuard g2(i->second->mutex);
- if (i->second->dispose) {
- sngls.push_back(i->second->singleton);
+ if (i->second->disposeSingleton.is()) {
+ sngls.push_back(i->second->disposeSingleton);
}
}
if (i->second->component.is()) {
@@ -976,21 +941,17 @@ void cppuhelper::ServiceManager::disposing() {
data_.singletons.swap(clear.singletons);
}
for (std::vector<
- css::uno::Reference<css::uno::XInterface> >::const_iterator i(
+ css::uno::Reference<css::lang::XComponent> >::const_iterator i(
sngls.begin());
i != sngls.end(); ++i)
{
- css::uno::Reference<css::lang::XComponent> comp(
- *i, css::uno::UNO_QUERY);
- if (comp.is()) {
- try {
- comp->dispose();
- } catch (css::uno::RuntimeException & e) {
- SAL_WARN(
- "cppuhelper",
- "Ignoring RuntimeException \"" << e.Message
- << "\" while disposing singleton");
- }
+ try {
+ (*i)->dispose();
+ } catch (css::uno::RuntimeException & e) {
+ SAL_WARN(
+ "cppuhelper",
+ "Ignoring RuntimeException \"" << e.Message
+ << "\" while disposing singleton");
}
}
for (std::vector<
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
index b6e506bfbd47..1e760ca78310 100644
--- a/cppuhelper/source/servicemanager.hxx
+++ b/cppuhelper/source/servicemanager.hxx
@@ -106,8 +106,7 @@ public:
new ImplementationInfo(
name, loader, uri, environment, constructorName, prefix,
alienContext, rdbFile)),
- constructor(0), status(STATUS_NEW),
- dispose(false)
+ constructor(0), status(STATUS_NEW), dispose(true)
{}
Implementation(
@@ -120,8 +119,7 @@ public:
theComponent):
info(new ImplementationInfo(name)), constructor(0),
factory1(theFactory1), factory2(theFactory2),
- component(theComponent), status(STATUS_LOADED),
- dispose(false)
+ component(theComponent), status(STATUS_LOADED), dispose(true)
{ assert(theFactory1.is() || theFactory2.is()); }
css::uno::Reference<css::uno::XInterface> createInstance(
@@ -146,8 +144,13 @@ public:
Status status;
osl::Mutex mutex;
- css::uno::Reference<css::uno::XInterface> singleton;
+ css::uno::Reference< css::lang::XComponent > disposeSingleton;
bool dispose;
+
+ private:
+ void updateDisposeSingleton(
+ bool singletonRequest,
+ css::uno::Reference<css::uno::XInterface> const & instance);
};
typedef std::map< rtl::OUString, boost::shared_ptr< Implementation > >