Author: fmeschbe
Date: Mon Sep 6 06:14:07 2010
New Revision: 992946
URL: http://svn.apache.org/viewvc?rev=992946&view=rev
Log:
SLING-1728 Apply version 2 of the patch to prevent potential deadlock
Modified:
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ServiceCache.java
Modified:
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ServiceCache.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ServiceCache.java?rev=992946&r1=992945&r2=992946&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ServiceCache.java
(original)
+++
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ServiceCache.java
Mon Sep 6 06:14:07 2010
@@ -49,7 +49,7 @@ public class ServiceCache implements Ser
public void dispose() {
this.bundleContext.removeServiceListener(this);
- for(final Reference ref : cache.values()) {
+ for (final Reference ref : cache.values()) {
if ( ref != NULL_REFERENCE ) {
this.bundleContext.ungetService(ref.reference);
}
@@ -66,33 +66,44 @@ public class ServiceCache implements Ser
public <ServiceType> ServiceType getService(Class<ServiceType> type) {
final String key = type.getName();
Reference reference = this.cache.get(key);
- if (reference == null ) {
- // if the service is not in the cache, we have to go into a
synchronized
- // block to avoid concurrent gets of the same service
+ if (reference == null) {
+
+ // get the service
+ ServiceReference ref = this.bundleContext.getServiceReference(key);
+ if (ref != null) {
+ final Object service = this.bundleContext.getService(ref);
+ if (service != null) {
+ reference = new Reference();
+ reference.service = service;
+ reference.reference = ref;
+ } else {
+ ref = null;
+ }
+ }
+
+ // assume missing service
+ if (reference == null) {
+ reference = NULL_REFERENCE;
+ }
+
+ // check to see whether another thread has not done the same thing
synchronized (this) {
- reference = this.cache.get(key);
- if ( reference == null ) {
- // try to get service from bundle context
- final ServiceReference ref =
this.bundleContext.getServiceReference(key);
- if (ref != null) {
- final Object service =
this.bundleContext.getService(ref);
- if ( service != null ) {
- reference = new Reference();
- reference.service = service;
- reference.reference = ref;
- }
- }
- if ( reference == null ) {
- reference = NULL_REFERENCE;
- }
+ Reference existing = this.cache.get(key);
+ if (existing == null) {
this.cache.put(key, reference);
+ ref = null;
+ } else {
+ reference = existing;
}
}
+ // unget the service if another thread was faster
+ if (ref != null) {
+ this.bundleContext.ungetService(ref);
+ }
}
- if ( reference == NULL_REFERENCE ) {
- return null;
- }
+
+ // return whatever we got (which may be null)
return (ServiceType) reference.service;
}