aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Besedin2011-09-19 11:40:52 (EDT)
committerOleg Besedin2011-09-19 11:40:52 (EDT)
commit8450070ff35df1025aebdbe59fb305b1a09b2a60 (patch)
treee1cc450888c7abc5f12394bbcdd51cb8e5dd2a10
parentc56ff7b31d46a97e0ecca46da3de1c447ba5e059 (diff)
downloadeclipse.platform.runtime-8450070ff35df1025aebdbe59fb305b1a09b2a60.zip
eclipse.platform.runtime-8450070ff35df1025aebdbe59fb305b1a09b2a60.tar.gz
eclipse.platform.runtime-8450070ff35df1025aebdbe59fb305b1a09b2a60.tar.bz2
Bug 357268 - Eclipse contexts: reduce overhead of invalidationsv20110919-1540
-rw-r--r--bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/Computation.java14
-rw-r--r--bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java70
-rw-r--r--bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/TrackableComputationExt.java8
-rw-r--r--bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/ValueComputation.java45
4 files changed, 119 insertions, 18 deletions
diff --git a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/Computation.java b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/Computation.java
index f88761b..8a7c365 100644
--- a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/Computation.java
+++ b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/Computation.java
@@ -14,7 +14,11 @@ import java.util.Set;
import org.eclipse.e4.core.internal.contexts.EclipseContext.Scheduled;
abstract public class Computation {
+
+ abstract protected int calcHashCode();
+ abstract public boolean equals(Object obj);
+ /* final */ protected int hashCode;
protected boolean validComputation = true;
public void handleInvalid(ContextChangeEvent event, Set<Scheduled> scheduled) {
@@ -29,4 +33,14 @@ abstract public class Computation {
validComputation = false;
}
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ protected void init() {
+ hashCode = calcHashCode();
+ }
+
+
} \ No newline at end of file
diff --git a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
index a68061d..3212c8e 100644
--- a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
+++ b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
@@ -22,7 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
-import java.util.Vector;
import org.eclipse.e4.core.contexts.IContextFunction;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
@@ -73,7 +72,50 @@ public class EclipseContext implements IEclipseContext {
}
}
- private Map<String, Vector<WeakReference<Computation>>> listeners = Collections.synchronizedMap(new HashMap<String, Vector<WeakReference<Computation>>>());
+ static class ComputationReference {
+
+ final private WeakReference<Computation> ref;
+
+ public ComputationReference(Computation computation) {
+ ref = new WeakReference<Computation>(computation);
+ }
+
+ public Computation get() {
+ Computation computation = ref.get();
+ if (computation == null)
+ return null;
+ if (computation.isValid())
+ return computation;
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ Computation computation = get();
+ if (computation == null)
+ return 0;
+ return computation.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Computation c1 = get();
+ Computation c2 = ((ComputationReference) obj).get();
+ if ((c1 == null) && (c2 == null))
+ return true;
+ if ((c1 == null) || (c2 == null))
+ return false;
+ return c1.equals(c2);
+ }
+ }
+
+ private Map<String, HashSet<ComputationReference>> listeners = Collections.synchronizedMap(new HashMap<String, HashSet<ComputationReference>>());
private Map<String, ValueComputation> localValueComputations = Collections.synchronizedMap(new HashMap<String, ValueComputation>());
private Set<Computation> activeRATs = new HashSet<Computation>();
@@ -272,10 +314,10 @@ public class EclipseContext implements IEclipseContext {
if (computation != null && computation.isValid()) {
computation.handleInvalid(event, scheduled);
}
- Vector<WeakReference<Computation>> namedComputations = listeners.get(name);
+ Set<ComputationReference> namedComputations = listeners.get(name);
if (namedComputations != null) {
int invalidListenersCount = 0;
- for (WeakReference<Computation> listenerRef : namedComputations) {
+ for (ComputationReference listenerRef : namedComputations) {
Computation listener = listenerRef.get();
if (listener != null && listener.isValid())
listener.handleInvalid(event, scheduled);
@@ -284,8 +326,8 @@ public class EclipseContext implements IEclipseContext {
}
// more than half of listeners are invalid, clean the listener list
if ((invalidListenersCount << 2) > namedComputations.size()) {
- Vector<WeakReference<Computation>> tmp = new Vector<WeakReference<Computation>>(namedComputations.size() - invalidListenersCount);
- for (WeakReference<Computation> listenerRef : namedComputations) {
+ HashSet<ComputationReference> tmp = new HashSet<ComputationReference>(namedComputations.size() - invalidListenersCount);
+ for (ComputationReference listenerRef : namedComputations) {
Computation listener = listenerRef.get();
if (listener != null && listener.isValid())
tmp.add(listenerRef);
@@ -410,12 +452,12 @@ public class EclipseContext implements IEclipseContext {
}
public void addDependency(String name, Computation computation) {
- Vector<WeakReference<Computation>> nameListeners = listeners.get(name);
+ HashSet<ComputationReference> nameListeners = listeners.get(name);
if (nameListeners == null) {
- nameListeners = new Vector<WeakReference<Computation>>();
+ nameListeners = new HashSet<ComputationReference>();
listeners.put(name, nameListeners);
}
- nameListeners.add(new WeakReference<Computation>(computation));
+ nameListeners.add(new ComputationReference(computation));
}
public void declareModifiable(String name) {
@@ -452,11 +494,11 @@ public class EclipseContext implements IEclipseContext {
}
public Set<Computation> getListeners() {
- Collection<Vector<WeakReference<Computation>>> collection = listeners.values();
+ Collection<HashSet<ComputationReference>> collection = listeners.values();
Set<Computation> comps = new HashSet<Computation>();
- for (Vector<WeakReference<Computation>> set : collection) {
- for (WeakReference<Computation> ref : set) {
+ for (Set<ComputationReference> set : collection) {
+ for (ComputationReference ref : set) {
Computation comp = ref.get();
if (comp != null && comp.isValid())
comps.add(comp);
@@ -679,11 +721,11 @@ public class EclipseContext implements IEclipseContext {
// This method is for debug only, do not use externally
public Set<Computation> getListeners(String name) {
- Vector<WeakReference<Computation>> tmp = listeners.get(name);
+ HashSet<ComputationReference> tmp = listeners.get(name);
if (tmp == null)
return null;
Set<Computation> result = new HashSet<Computation>(tmp.size());
- for (WeakReference<Computation> ref : tmp) {
+ for (ComputationReference ref : tmp) {
Computation listener = ref.get();
if (listener != null && listener.isValid())
result.add(listener);
diff --git a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/TrackableComputationExt.java b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/TrackableComputationExt.java
index fcbd937..db6b3a4 100644
--- a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/TrackableComputationExt.java
+++ b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/TrackableComputationExt.java
@@ -18,15 +18,21 @@ import org.eclipse.e4.core.internal.contexts.EclipseContext.Scheduled;
public class TrackableComputationExt extends Computation {
final private IEclipseContext originatingContext;
- private RunAndTrack runnable;
+ final private RunAndTrack runnable;
+
private ContextChangeEvent cachedEvent;
public TrackableComputationExt(RunAndTrack runnable, IEclipseContext originatingContext) {
this.runnable = runnable;
this.originatingContext = originatingContext;
+ init();
}
public int hashCode() {
+ return hashCode;
+ }
+
+ protected int calcHashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((originatingContext == null) ? 0 : originatingContext.hashCode());
diff --git a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/ValueComputation.java b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/ValueComputation.java
index af2fe1f..1bba081 100644
--- a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/ValueComputation.java
+++ b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/ValueComputation.java
@@ -19,16 +19,18 @@ public class ValueComputation extends Computation {
final static private Object NotAValue = new Object();
+ final private IContextFunction function;
+ final private EclipseContext originatingContext;
+ final private String name;
+
private Object cachedValue = NotAValue;
- private IContextFunction function;
- private EclipseContext originatingContext;
private boolean computing; // cycle detection
- private String name;
public ValueComputation(String name, IEclipseContext originatingContext, IContextFunction computedValue) {
this.originatingContext = (EclipseContext) originatingContext;
this.function = computedValue;
this.name = name;
+ init();
}
public void handleInvalid(ContextChangeEvent event, Set<Scheduled> scheduled) {
@@ -66,4 +68,41 @@ public class ValueComputation extends Computation {
return super.toString();
return function.toString();
}
+
+ protected int calcHashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((function == null) ? 0 : function.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((originatingContext == null) ? 0 : originatingContext.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ValueComputation other = (ValueComputation) obj;
+ if (function == null) {
+ if (other.function != null)
+ return false;
+ } else if (!function.equals(other.function))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (originatingContext == null) {
+ if (other.originatingContext != null)
+ return false;
+ } else if (!originatingContext.equals(other.originatingContext))
+ return false;
+ return true;
+ }
+
} \ No newline at end of file