Kaydet (Commit) 874c4818 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Simplify service manager's tracking of singletons

It only tracks whether to dispose a singleton instance now, and (at least
conceptually) no longer remembers the single instance (apart from what is
necessary in order to call dispose on it), as the underlying implementation
already needs to keep track of that to support direct calls of constructor
functions.

Change-Id: I154bf05438e1db099c1c5ffb1c56377725c6bfc6
üst 138bd3d6
...@@ -701,43 +701,19 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance( ...@@ -701,43 +701,19 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance(
css::uno::Reference<css::uno::XComponentContext> const & context, css::uno::Reference<css::uno::XComponentContext> const & context,
bool singletonRequest) bool singletonRequest)
{ {
if (info->singletons.empty()) { css::uno::Reference<css::uno::XInterface> inst;
assert(!singletonRequest);
if (constructor != 0) { if (constructor != 0) {
// the interface is already acquired, don't acquire here inst.set(
return css::uno::Reference<css::uno::XInterface>( (*constructor)(context.get(), css::uno::Sequence<css::uno::Any>()),
(*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();
} 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); SAL_NO_ACQUIRE);
} else if (factory1.is()) { } else if (factory1.is()) {
singleton = factory1->createInstanceWithContext(context); inst = factory1->createInstanceWithContext(context);
} else { } else {
assert(factory2.is()); assert(factory2.is());
singleton = factory2->createInstance(); inst = factory2->createInstance();
}
dispose = singleton.is() && !singletonRequest;
return singleton;
} }
updateDisposeSingleton(singletonRequest, inst);
return inst;
} }
css::uno::Reference<css::uno::XInterface> css::uno::Reference<css::uno::XInterface>
...@@ -745,65 +721,54 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments( ...@@ -745,65 +721,54 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
css::uno::Reference<css::uno::XComponentContext> const & context, css::uno::Reference<css::uno::XComponentContext> const & context,
bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments) bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
{ {
if (info->singletons.empty()) { css::uno::Reference<css::uno::XInterface> inst;
assert(!singletonRequest);
if (constructor != 0) { if (constructor != 0) {
// the interface is already acquired, don't acquire here inst.set((*constructor)(context.get(), arguments), SAL_NO_ACQUIRE);
css::uno::Reference<css::uno::XInterface> inst( //HACK: The constructor will either observe arguments and return inst
(*constructor)(context.get(), arguments), SAL_NO_ACQUIRE); // that does not implement XInitialization (or null), or ignore
// arguments and return inst that implements XInitialization; this
// HACK: The service can implement XInitialization too. // should be removed again once XInitialization-based implementations
// It should be removed when converting to constructor-based // have become rare:
// initialization, but in case somebody forgets, be safe, and css::uno::Reference<css::lang::XInitialization> init(
// call it anyway for the moment.
css::uno::Reference<css::lang::XInitialization> xinit(
inst, css::uno::UNO_QUERY); inst, css::uno::UNO_QUERY);
if (xinit.is()) { if (init.is()) {
xinit->initialize(arguments); init->initialize(arguments);
} }
return inst; return inst;
} } else if (factory1.is()) {
if (factory1.is()) { inst = factory1->createInstanceWithArgumentsAndContext(
return factory1->createInstanceWithArgumentsAndContext(
arguments, context); arguments, context);
}
assert(factory2.is());
return factory2->createInstanceWithArguments(arguments);
} else { } else {
osl::MutexGuard g(mutex); //TODO: must be a non-recursive mutex assert(factory2.is());
if (singleton.is()) { inst = factory2->createInstanceWithArguments(arguments);
SAL_WARN( }
"cppuhelper", updateDisposeSingleton(singletonRequest, inst);
"createInstanceWithArguments request for already instantiated" return inst;
" singleton implementation " << info->name); }
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) { if (singletonRequest) {
osl::MutexGuard g(mutex);
disposeSingleton.clear();
dispose = false; 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;
} }
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);
}
} 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( ...@@ -938,7 +903,7 @@ void cppuhelper::ServiceManager::loadImplementation(
} }
void cppuhelper::ServiceManager::disposing() { 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; std::vector< css::uno::Reference< css::lang::XComponent > > comps;
Data clear; Data clear;
{ {
...@@ -950,8 +915,8 @@ void cppuhelper::ServiceManager::disposing() { ...@@ -950,8 +915,8 @@ void cppuhelper::ServiceManager::disposing() {
assert(i->second.get() != 0); assert(i->second.get() != 0);
if (!i->second->info->singletons.empty()) { if (!i->second->info->singletons.empty()) {
osl::MutexGuard g2(i->second->mutex); osl::MutexGuard g2(i->second->mutex);
if (i->second->dispose) { if (i->second->disposeSingleton.is()) {
sngls.push_back(i->second->singleton); sngls.push_back(i->second->disposeSingleton);
} }
} }
} }
...@@ -962,8 +927,8 @@ void cppuhelper::ServiceManager::disposing() { ...@@ -962,8 +927,8 @@ void cppuhelper::ServiceManager::disposing() {
assert(i->second.get() != 0); assert(i->second.get() != 0);
if (!i->second->info->singletons.empty()) { if (!i->second->info->singletons.empty()) {
osl::MutexGuard g2(i->second->mutex); osl::MutexGuard g2(i->second->mutex);
if (i->second->dispose) { if (i->second->disposeSingleton.is()) {
sngls.push_back(i->second->singleton); sngls.push_back(i->second->disposeSingleton);
} }
} }
if (i->second->component.is()) { if (i->second->component.is()) {
...@@ -976,15 +941,12 @@ void cppuhelper::ServiceManager::disposing() { ...@@ -976,15 +941,12 @@ void cppuhelper::ServiceManager::disposing() {
data_.singletons.swap(clear.singletons); data_.singletons.swap(clear.singletons);
} }
for (std::vector< for (std::vector<
css::uno::Reference<css::uno::XInterface> >::const_iterator i( css::uno::Reference<css::lang::XComponent> >::const_iterator i(
sngls.begin()); sngls.begin());
i != sngls.end(); ++i) i != sngls.end(); ++i)
{ {
css::uno::Reference<css::lang::XComponent> comp(
*i, css::uno::UNO_QUERY);
if (comp.is()) {
try { try {
comp->dispose(); (*i)->dispose();
} catch (css::uno::RuntimeException & e) { } catch (css::uno::RuntimeException & e) {
SAL_WARN( SAL_WARN(
"cppuhelper", "cppuhelper",
...@@ -992,7 +954,6 @@ void cppuhelper::ServiceManager::disposing() { ...@@ -992,7 +954,6 @@ void cppuhelper::ServiceManager::disposing() {
<< "\" while disposing singleton"); << "\" while disposing singleton");
} }
} }
}
for (std::vector< for (std::vector<
css::uno::Reference< css::lang::XComponent > >::const_iterator i( css::uno::Reference< css::lang::XComponent > >::const_iterator i(
comps.begin()); comps.begin());
......
...@@ -106,8 +106,7 @@ public: ...@@ -106,8 +106,7 @@ public:
new ImplementationInfo( new ImplementationInfo(
name, loader, uri, environment, constructorName, prefix, name, loader, uri, environment, constructorName, prefix,
alienContext, rdbFile)), alienContext, rdbFile)),
constructor(0), status(STATUS_NEW), constructor(0), status(STATUS_NEW), dispose(true)
dispose(false)
{} {}
Implementation( Implementation(
...@@ -120,8 +119,7 @@ public: ...@@ -120,8 +119,7 @@ public:
theComponent): theComponent):
info(new ImplementationInfo(name)), constructor(0), info(new ImplementationInfo(name)), constructor(0),
factory1(theFactory1), factory2(theFactory2), factory1(theFactory1), factory2(theFactory2),
component(theComponent), status(STATUS_LOADED), component(theComponent), status(STATUS_LOADED), dispose(true)
dispose(false)
{ assert(theFactory1.is() || theFactory2.is()); } { assert(theFactory1.is() || theFactory2.is()); }
css::uno::Reference<css::uno::XInterface> createInstance( css::uno::Reference<css::uno::XInterface> createInstance(
...@@ -146,8 +144,13 @@ public: ...@@ -146,8 +144,13 @@ public:
Status status; Status status;
osl::Mutex mutex; osl::Mutex mutex;
css::uno::Reference<css::uno::XInterface> singleton; css::uno::Reference< css::lang::XComponent > disposeSingleton;
bool dispose; bool dispose;
private:
void updateDisposeSingleton(
bool singletonRequest,
css::uno::Reference<css::uno::XInterface> const & instance);
}; };
typedef std::map< rtl::OUString, boost::shared_ptr< Implementation > > typedef std::map< rtl::OUString, boost::shared_ptr< Implementation > >
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment