From 376f5664516512cf7d6c4e4ff0f4379afac74f74 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Wed, 12 Nov 2014 14:47:39 -0600 Subject: [PATCH] Omaha #3810 Make D2D nsharp more thread safe. Former-commit-id: 31901b563e4169cc44494134e3cac55a5542a79f --- .../.settings/org.eclipse.jdt.core.prefs | 8 -- .../META-INF/MANIFEST.MF | 4 +- .../viz/d2d/nsharp/rsc/D2DNSharpResource.java | 129 +++++++++++------- 3 files changed, 78 insertions(+), 63 deletions(-) delete mode 100644 cave/com.raytheon.uf.viz.d2d.nsharp/.settings/org.eclipse.jdt.core.prefs diff --git a/cave/com.raytheon.uf.viz.d2d.nsharp/.settings/org.eclipse.jdt.core.prefs b/cave/com.raytheon.uf.viz.d2d.nsharp/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 8269ff7d8c..0000000000 --- a/cave/com.raytheon.uf.viz.d2d.nsharp/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Sat Apr 09 08:47:34 CDT 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/cave/com.raytheon.uf.viz.d2d.nsharp/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.d2d.nsharp/META-INF/MANIFEST.MF index a14bddc91c..e20f99d2e9 100644 --- a/cave/com.raytheon.uf.viz.d2d.nsharp/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.uf.viz.d2d.nsharp/META-INF/MANIFEST.MF @@ -2,9 +2,9 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: D2D Nsharp Bundle-SymbolicName: com.raytheon.uf.viz.d2d.nsharp;singleton:=true -Bundle-Version: 1.14.0.qualifier +Bundle-Version: 1.14.1.qualifier Bundle-Vendor: RAYTHEON -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Require-Bundle: com.raytheon.uf.viz.core;bundle-version="1.14.0", com.raytheon.viz.ui;bundle-version="1.14.0", diff --git a/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpResource.java b/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpResource.java index ac33ae8dad..4cf750d694 100644 --- a/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpResource.java +++ b/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpResource.java @@ -45,7 +45,7 @@ import com.raytheon.uf.viz.core.drawables.IRenderableDisplay; import com.raytheon.uf.viz.core.drawables.PaintProperties; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.rsc.AbstractVizResource; -import com.raytheon.uf.viz.core.rsc.IResourceDataChanged; +import com.raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType; import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.RenderingOrderFactory.ResourceOrder; import com.raytheon.uf.viz.core.rsc.ResourceProperties; @@ -53,16 +53,17 @@ import com.raytheon.uf.viz.d2d.nsharp.display.D2DNSharpPartListener; /** * - * Minimal wrapper arounf ncep resource to handle updates and frame counts and + * Minimal wrapper around ncep resource to handle updates and frame counts and * initializing data from a requestable resource data. * *
  * 
  * SOFTWARE HISTORY
  * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 14, 2011            bsteffen     Initial creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Apr 14, 2011           bsteffen    Initial creation
+ * Nov 12, 2014  3810     bsteffen    Synchronize access to dataTimes and pdos.
  * 
  * 
* @@ -72,7 +73,10 @@ import com.raytheon.uf.viz.d2d.nsharp.display.D2DNSharpPartListener; public class D2DNSharpResource extends AbstractVizResource { - // A map of all the plugin data objects for times we have data. + /* This object should be synchronized whenever accessing dataTimes or pdos. */ + private final Object timeLock = new Object(); + + /* A map of all the plugin data objects for times we have data. */ private Map pdos = new HashMap(); private List soundingsToRemove = new ArrayList(); @@ -87,13 +91,12 @@ public class D2DNSharpResource extends protected IStatus run(IProgressMonitor monitor) { D2DNSharpDataObject pdo = dataRequestQueue.poll(); while (pdo != null && !monitor.isCanceled()) { - if (pdos.get(pdo.getDataTime()) != pdo) { - pdo = dataRequestQueue.poll(); - continue; + if (isDataObjectCurrent(pdo)) { + resourceData.populateDataObject(pdo); + dataResponseQueue.add(pdo); + issueRefresh(); } - resourceData.populateDataObject(pdo); - dataResponseQueue.add(pdo); - issueRefresh(); + pdo = dataRequestQueue.poll(); } return Status.OK_STATUS; @@ -106,15 +109,19 @@ public class D2DNSharpResource extends public D2DNSharpResource(D2DNSharpResourceData resourceData, LoadProperties loadProperties) { super(resourceData, loadProperties); - this.dataTimes = new ArrayList(); + synchronized (timeLock) { + this.dataTimes = new ArrayList(); + } } protected void addDataObject(D2DNSharpDataObject pdo) { - if (!this.dataTimes.contains(pdo.getDataTime())) { - this.dataTimes.add(pdo.getDataTime()); - Collections.sort(this.dataTimes); + synchronized (timeLock) { + if (!this.dataTimes.contains(pdo.getDataTime())) { + this.dataTimes.add(pdo.getDataTime()); + Collections.sort(this.dataTimes); + } + pdos.put(pdo.getDataTime(), pdo); } - pdos.put(pdo.getDataTime(), pdo); dataRequestQueue.offer(pdo); dataRequestJob.schedule(); } @@ -123,9 +130,11 @@ public class D2DNSharpResource extends protected void paintInternal(IGraphicsTarget target, PaintProperties paintProps) throws VizException { NsharpResourceHandler handler = getHandler(); - // Last time I checked if you try to add or remove data from nsharp on - // non-UI threads it can cause major sync issues so all changes to - // nsharp are done in the paint loop. + /* + * Last time I checked if you try to add or remove data from nsharp on + * non-UI threads it can cause major sync issues so all changes to + * nsharp are done in the paint loop. + */ if (!soundingsToRemove.isEmpty()) { List soundingsToRemove = this.soundingsToRemove; this.soundingsToRemove = new ArrayList(); @@ -137,12 +146,9 @@ public class D2DNSharpResource extends Map> myDataMap = new HashMap>(); D2DNSharpDataObject pdo = dataResponseQueue.poll(); while (pdo != null) { - if (pdos.get(pdo.getDataTime()) == pdo) { - if (pdo.getLayers() != null) { - stnInfo = pdo.getStationInfo(); - myDataMap.put(stnInfo.getStnDisplayInfo(), - pdo.getLayers()); - } + if (isDataObjectCurrent(pdo) && pdo.getLayers() != null) { + stnInfo = pdo.getStationInfo(); + myDataMap.put(stnInfo.getStnDisplayInfo(), pdo.getLayers()); } pdo = dataResponseQueue.poll(); } @@ -154,7 +160,7 @@ public class D2DNSharpResource extends } } - private NsharpResourceHandler getHandler() throws VizException { + private NsharpResourceHandler getHandler() { List paneRscs = descriptor .getResourceList().getResourcesByTypeAsType( NsharpAbstractPaneResource.class); @@ -176,37 +182,34 @@ public class D2DNSharpResource extends @Override protected void initInternal(IGraphicsTarget target) throws VizException { getHandler().setSoundingType(resourceData.getSoundingType()); - // listen for updates - resourceData.addChangeListener(new IResourceDataChanged() { - - @Override - public void resourceChanged(ChangeType type, Object object) { - if (type == ChangeType.DATA_UPDATE - && object instanceof Object[]) { - for (Object obj : (Object[]) object) { - if (obj instanceof D2DNSharpDataObject) { - addDataObject((D2DNSharpDataObject) obj); - } - } - } - } - - }); partListener = new D2DNSharpPartListener(this); partListener.enable(); } + @Override + protected void resourceDataChanged(ChangeType type, Object object) { + if (type == ChangeType.DATA_UPDATE && object instanceof Object[]) { + for (Object obj : (Object[]) object) { + if (obj instanceof D2DNSharpDataObject) { + addDataObject((D2DNSharpDataObject) obj); + } + } + } + } + @Override public void remove(DataTime dataTime) { D2DNSharpDataObject pdo = null; - pdo = pdos.remove(dataTime); + synchronized (timeLock) { + pdo = pdos.remove(dataTime); + dataTimes.remove(dataTime); + } if (pdo != null) { NsharpStationInfo stnInfo = pdo.getStationInfo(); if (stnInfo != null) { soundingsToRemove.add(stnInfo.getStnDisplayInfo()); } } - dataTimes.remove(dataTime); } @Override @@ -223,8 +226,11 @@ public class D2DNSharpResource extends public Collection getTimeLineElements() { List elements = new ArrayList(); - for (DataTime time : dataTimes) { - elements.add(pdos.get(time).getStationInfo().getStnDisplayInfo()); + synchronized (timeLock) { + for (DataTime time : dataTimes) { + elements.add(pdos.get(time).getStationInfo() + .getStnDisplayInfo()); + } } return elements; } @@ -237,18 +243,35 @@ public class D2DNSharpResource extends @Override public ResourceOrder getResourceOrder() { - // Have to be highest resource since the builtin nsharp resources are - // unknown and they have to be at index 0 on the list or nsharp code - // breaks. + /* + * Have to be highest resource since the builtin nsharp resources are + * unknown and they have to be at index 0 on the list or nsharp code + * breaks. + */ return ResourceOrder.HIGHEST; } @Override protected void setProperties(ResourceProperties properties) { - // Have to be highest resource since the builtin nsharp resources are - // unknown and they have to be at index 0 on the list or nsharp code - // breaks. + /* + * Have to be highest resource since the builtin nsharp resources are + * unknown and they have to be at index 0 on the list or nsharp code + * breaks. + */ properties.setRenderingOrder(ResourceOrder.HIGHEST); } + @Override + public DataTime[] getDataTimes() { + synchronized (timeLock) { + return super.getDataTimes(); + } + } + + private boolean isDataObjectCurrent(D2DNSharpDataObject pdo) { + synchronized (timeLock) { + return pdos.get(pdo.getDataTime()) == pdo; + } + } + }