aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Ross2011-11-08 11:33:36 (EST)
committerJohn Ross2011-11-08 11:33:36 (EST)
commitb854d31f31eb59741811b41ba9b4b18b47a05128 (patch)
tree2e966c3414486122e32b6e32a11d1962609981b3
parentef3fa6e650dbe7273d2721dd85d92296072a374d (diff)
downloadrt.equinox.bundles-b854d31f31eb59741811b41ba9b4b18b47a05128.zip
rt.equinox.bundles-b854d31f31eb59741811b41ba9b4b18b47a05128.tar.gz
rt.equinox.bundles-b854d31f31eb59741811b41ba9b4b18b47a05128.tar.bz2
Bug 362232 - [coordinator] Add support for the new, mandatory orphaned coordination requirement.
Removed the set of weak references maintained by CoordinationWeakReference. Each CoordinationImpl now maintains a strong reference to its associated CoordinationWeakReference. CoordinationImpl now maintains a CoordinationReferent that is a different instance than the one returned to the initiator. It is used to pass the referent to clients other than the initiator without needing to create new objects.
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java21
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java4
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java15
-rw-r--r--bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java19
4 files changed, 32 insertions, 27 deletions
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java
index 5e22f5a..1f43839 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java
@@ -27,6 +27,10 @@ import org.osgi.service.coordinator.Participant;
import org.osgi.service.log.LogService;
public class CoordinationImpl implements Coordination {
+ // Holds a strong reference to the CoordinationWeakReference object associated
+ // with this CoordinationImpl. Serves no other purpose. Needs no guarding.
+ CoordinationWeakReference reference;
+
private volatile Throwable failure;
private volatile boolean terminated;
@@ -39,6 +43,9 @@ public class CoordinationImpl implements Coordination {
private final long id;
private final String name;
private final List<Participant> participants;
+ // Store a referent to be used by clients other than the initiator. It must
+ // not be a reference to the referent returned to the initiator.
+ private final CoordinationReferent referent;
private final Map<Class<?>, Object> variables;
public CoordinationImpl(long id, String name, long timeout, CoordinatorImpl coordinator) {
@@ -50,6 +57,8 @@ public class CoordinationImpl implements Coordination {
this.coordinator = coordinator;
participants = Collections.synchronizedList(new ArrayList<Participant>());
variables = new HashMap<Class<?>, Object>();
+ // Not an escaping 'this' reference. It will not escape the thread calling the constructor.
+ referent = new CoordinationReferent(this);
}
public void addParticipant(Participant participant) throws CoordinationException {
@@ -127,7 +136,6 @@ public class CoordinationImpl implements Coordination {
}
// Unwind the stack in case there are other coordinations higher
// up than this one.
- CoordinationReferent referent = new CoordinationReferent(this);
while (!coordinator.peek().equals(referent)) {
try {
coordinator.peek().end();
@@ -147,7 +155,6 @@ public class CoordinationImpl implements Coordination {
Exception exception = null;
// No additional synchronization is needed here because the participant
// list will not be modified post termination.
- CoordinationReferent referent = new CoordinationReferent(this);
for (Participant participant : participants) {
try {
participant.ended(referent);
@@ -234,7 +241,6 @@ public class CoordinationImpl implements Coordination {
// Notify participants this coordination has failed.
// No additional synchronization is needed here because the participant
// list will not be modified post termination.
- CoordinationReferent referent = new CoordinationReferent(this);
for (Participant participant : participants) {
try {
participant.failed(referent);
@@ -259,7 +265,7 @@ public class CoordinationImpl implements Coordination {
coordinator.checkPermission(CoordinationPermission.ADMIN, name);
if (enclosingCoordination == null)
return null;
- return new CoordinationReferent(enclosingCoordination);
+ return enclosingCoordination.getReferent();
}
public Throwable getFailure() {
@@ -319,7 +325,7 @@ public class CoordinationImpl implements Coordination {
checkTerminated();
coordinator.push(this);
}
- return new CoordinationReferent(this);
+ return referent;
}
synchronized Date getDeadline() {
@@ -329,6 +335,11 @@ public class CoordinationImpl implements Coordination {
LogService getLogService() {
return coordinator.getLogService();
}
+
+ // Return the referent to be used by clients other than the initiator.
+ CoordinationReferent getReferent() {
+ return referent;
+ }
synchronized void setTimerTask(TimerTask timerTask) {
this.timerTask = timerTask;
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java
index 6f13e99..dc6ff6e 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationReferent.java
@@ -99,8 +99,4 @@ public class CoordinationReferent implements Coordination {
public int hashCode() {
return coordination.hashCode();
}
-
- CoordinationImpl getDelegate() {
- return coordination;
- }
}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java
index d2d25de..7c7d90c 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationWeakReference.java
@@ -12,9 +12,6 @@ package org.eclipse.equinox.coordinator;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
import org.eclipse.osgi.util.NLS;
import org.osgi.service.coordinator.Coordination;
@@ -23,18 +20,10 @@ import org.osgi.service.log.LogService;
public class CoordinationWeakReference extends WeakReference<CoordinationReferent> {
private static final ReferenceQueue<CoordinationReferent> referenceQueue = new ReferenceQueue<CoordinationReferent>();
- private static final Set<CoordinationWeakReference> references = Collections.synchronizedSet(new HashSet<CoordinationWeakReference>());
-
- public static CoordinationWeakReference newInstance(CoordinationReferent referent) {
- CoordinationWeakReference reference = new CoordinationWeakReference(referent);
- references.add(reference);
- return reference;
- }
public static void processOrphanedCoordinations() {
CoordinationWeakReference r;
while ((r = (CoordinationWeakReference)referenceQueue.poll()) != null) {
- references.remove(r);
CoordinationImpl c = r.getCoordination();
try {
c.fail(Coordination.ORPHANED);
@@ -61,11 +50,11 @@ public class CoordinationWeakReference extends WeakReference<CoordinationReferen
private final CoordinationImpl coordination;
- private CoordinationWeakReference(CoordinationReferent referent) {
+ public CoordinationWeakReference(CoordinationReferent referent, CoordinationImpl coordination) {
super(referent, referenceQueue);
- coordination = referent.getDelegate();
if (coordination == null)
throw new NullPointerException();
+ this.coordination = coordination;
}
public CoordinationImpl getCoordination() {
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java
index df748c3..1fc3ee7 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java
@@ -119,13 +119,21 @@ public class CoordinatorImpl implements Coordinator {
CoordinationWeakReference.processOrphanedCoordinations();
// This method requires the INITIATE permission. No bundle check is done.
checkPermission(CoordinationPermission.INITIATE, name);
+ // Create the coordination object itself, which will store its own instance
+ // of a referent to be returned to clients other than the initiator.
CoordinationImpl coordination = new CoordinationImpl(getNextId(), name, timeout, this);
+ // Create the referent to be returned to the initiator.
CoordinationReferent referent = new CoordinationReferent(coordination);
+ // Create a weak reference to the referent returned to the initiator. No other
+ // references to the initiator's referent must be maintained outside of this
+ // method. A strong reference to the CoordinationWeakReference must be maintained
+ // by the coordination in order to avoid garbage collection. It serves no other
+ // purpose. Just "set it and forget it".
+ coordination.reference = new CoordinationWeakReference(referent, coordination);
synchronized (this) {
if (shutdown)
throw new IllegalStateException(Messages.CoordinatorShutdown);
synchronized (CoordinatorImpl.class) {
- CoordinationWeakReference.newInstance(referent);
coordinations.add(coordination);
idToCoordination.put(new Long(coordination.getId()), coordination);
}
@@ -135,6 +143,7 @@ public class CoordinatorImpl implements Coordinator {
coordination.setTimerTask(timerTask);
schedule(timerTask, coordination.getDeadline());
}
+ // Make sure to return the referent targeted towards the initiator here.
return referent;
}
@@ -152,7 +161,7 @@ public class CoordinatorImpl implements Coordinator {
synchronized (CoordinatorImpl.class) {
CoordinationImpl c = idToCoordination.get(new Long(id));
if (c != null)
- result = new CoordinationReferent(c);
+ result = c.getReferent();
}
if (result != null && !result.isTerminated()) {
try {
@@ -177,7 +186,7 @@ public class CoordinatorImpl implements Coordinator {
continue;
try {
checkPermission(CoordinationPermission.ADMIN, coordination.getName());
- result.add(new CoordinationReferent(coordination));
+ result.add(coordination.getReferent());
} catch (SecurityException e) {
logService.log(LogService.LOG_DEBUG, Messages.GetCoordinationNotPermitted, e);
}
@@ -192,7 +201,7 @@ public class CoordinatorImpl implements Coordinator {
CoordinationImpl c = coordinationStack.get().peek();
if (c == null)
return null;
- return new CoordinationReferent(c);
+ return c.getReferent();
}
public Coordination pop() {
@@ -200,7 +209,7 @@ public class CoordinatorImpl implements Coordinator {
CoordinationImpl c = coordinationStack.get().peek();
if (c == null) return null;
checkPermission(CoordinationPermission.INITIATE, c.getName());
- return new CoordinationReferent(coordinationStack.get().pop());
+ return coordinationStack.get().pop().getReferent();
}
CoordinationImpl addParticipant(Participant participant, CoordinationImpl coordination) {