Ticket #11689: 0001-Revert-Temporary-fix-lockups-on-data-layer-removal-w.patch

File 0001-Revert-Temporary-fix-lockups-on-data-layer-removal-w.patch, 17.5 KB (added by michael2402, 10 years ago)
  • src/org/openstreetmap/josm/gui/MapView.java

    From faadcb49231b0a639a0e1e47783423381b8c9022 Mon Sep 17 00:00:00 2001
    From: Michael Zangl <michael.zangl@student.kit.edu>
    Date: Thu, 6 Aug 2015 14:02:04 +0200
    Subject: [PATCH 1/3] Revert "Temporary fix lockups on data layer removal when
     Validation layer is present"
    
    This reverts commit f3f0ab13d3c24ceb75494616fb4fbb187dc1eac0.
    ---
     src/org/openstreetmap/josm/gui/MapView.java | 220 +++++++++++++++++++---------
     1 file changed, 154 insertions(+), 66 deletions(-)
    
    diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java
    index bbe824a..ef6d0e8 100644
    a b import java.util.List;  
    3131import java.util.ListIterator;
    3232import java.util.Set;
    3333import java.util.concurrent.CopyOnWriteArrayList;
     34import java.util.concurrent.locks.ReentrantReadWriteLock;
    3435
    3536import javax.swing.AbstractButton;
    3637import javax.swing.ActionMap;
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    200201     * @param newLayer The new active layer.
    201202     */
    202203    protected void fireActiveLayerChanged(Layer oldLayer, Layer newLayer) {
     204        checkLayerLockNotHeld();
    203205        for (LayerChangeListener l : layerChangeListeners) {
    204206            l.activeLayerChange(oldLayer, newLayer);
    205207        }
    206208    }
    207209
    208210    protected void fireLayerAdded(Layer newLayer) {
     211        checkLayerLockNotHeld();
    209212        for (MapView.LayerChangeListener l : MapView.layerChangeListeners) {
    210213            l.layerAdded(newLayer);
    211214        }
    212215    }
    213216
    214217    protected void fireLayerRemoved(Layer layer) {
     218        checkLayerLockNotHeld();
    215219        for (MapView.LayerChangeListener l : MapView.layerChangeListeners) {
    216220            l.layerRemoved(layer);
    217221        }
    218222    }
    219223
    220224    protected void fireEditLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     225        checkLayerLockNotHeld();
    221226        for (EditLayerChangeListener l : editLayerChangeListeners) {
    222227            l.editLayerChanged(oldLayer, newLayer);
    223228        }
    224229    }
    225230
    226231    /**
     232     * This is a simple invariant check that tests if the {@link #layerLock} is not write locked.
     233     * This should be the case whenever a layer listener is invoked.
     234     */
     235    private void checkLayerLockNotHeld() {
     236        if (layerLock.isWriteLockedByCurrentThread()) {
     237            Main.warn("layerLock is write-held while a listener was called.");
     238        }
     239    }
     240
     241    /**
    227242     * A list of all layers currently loaded. Locked by {@link #layerLock}.
    228243     */
    229244    private final transient List<Layer> layers = new ArrayList<>();
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    234249     * <p>
    235250     * The read lock is always held while those fields are read or while layer change listeners are fired.
    236251     */
    237     //private final ReentrantReadWriteLock layerLock = new ReentrantReadWriteLock();
     252    private final ReentrantReadWriteLock layerLock = new ReentrantReadWriteLock();
    238253
    239254    /**
    240255     * The play head marker: there is only one of these so it isn't in any specific layer
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    360375     * @param layer the GPX layer
    361376     */
    362377    protected void addGpxLayer(GpxLayer layer) {
    363         synchronized (layers) {
     378        layerLock.writeLock().lock();
     379        try {
    364380            if (layers.isEmpty()) {
    365381                layers.add(layer);
    366382                return;
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    376392                }
    377393            }
    378394            layers.add(0, layer);
     395        } finally {
     396            layerLock.writeLock().unlock();
    379397        }
    380398    }
    381399
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    390408        Layer oldActiveLayer = activeLayer;
    391409        OsmDataLayer oldEditLayer = editLayer;
    392410
    393         synchronized (layers) {
    394             if (layer instanceof MarkerLayer && playHeadMarker == null) {
    395                 playHeadMarker = PlayHeadMarker.create();
    396             }
     411        layerLock.writeLock().lock();
     412        layerLock.readLock().lock();
     413        try {
     414            try {
     415                if (layer instanceof MarkerLayer && playHeadMarker == null) {
     416                    playHeadMarker = PlayHeadMarker.create();
     417                }
    397418
    398             if (layer instanceof GpxLayer) {
    399                 addGpxLayer((GpxLayer) layer);
    400             } else if (layers.isEmpty()) {
    401                 layers.add(layer);
    402             } else if (layer.isBackgroundLayer()) {
    403                 int i = 0;
    404                 for (; i < layers.size(); i++) {
    405                     if (layers.get(i).isBackgroundLayer()) {
    406                         break;
     419                if (layer instanceof GpxLayer) {
     420                    addGpxLayer((GpxLayer) layer);
     421                } else if (layers.isEmpty()) {
     422                    layers.add(layer);
     423                } else if (layer.isBackgroundLayer()) {
     424                    int i = 0;
     425                    for (; i < layers.size(); i++) {
     426                        if (layers.get(i).isBackgroundLayer()) {
     427                            break;
     428                        }
    407429                    }
     430                    layers.add(i, layer);
     431                } else {
     432                    layers.add(0, layer);
    408433                }
    409                 layers.add(i, layer);
    410             } else {
    411                 layers.add(0, layer);
    412             }
    413434
    414             if (isOsmDataLayer || oldActiveLayer == null) {
    415                 // autoselect the new layer
    416                 listenersToFire.addAll(setActiveLayer(layer, true));
     435                if (isOsmDataLayer || oldActiveLayer == null) {
     436                    // autoselect the new layer
     437                    listenersToFire.addAll(setActiveLayer(layer, true));
     438                }
     439            } finally {
     440                layerLock.writeLock().unlock();
    417441            }
    418442
    419443            fireLayerAdded(layer);
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    424448            layer.addPropertyChangeListener(this);
    425449            Main.addProjectionChangeListener(layer);
    426450            AudioPlayer.reset();
     451        } finally {
     452            layerLock.readLock().unlock();
    427453        }
    428454        if (!listenersToFire.isEmpty()) {
    429455            repaint();
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    432458
    433459    @Override
    434460    protected DataSet getCurrentDataSet() {
    435         synchronized (layers) {
     461        layerLock.readLock().lock();
     462        try {
    436463            if (editLayer != null)
    437464                return editLayer.data;
    438465            else
    439466                return null;
     467        } finally {
     468            layerLock.readLock().unlock();
    440469        }
    441470    }
    442471
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    446475     * @return true if the active data layer (edit layer) is drawable, false otherwise
    447476     */
    448477    public boolean isActiveLayerDrawable() {
    449         synchronized (layers) {
     478        layerLock.readLock().lock();
     479        try {
    450480            return editLayer != null;
     481        } finally {
     482            layerLock.readLock().unlock();
    451483        }
    452484    }
    453485
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    457489     * @return true if the active data layer (edit layer) is visible, false otherwise
    458490     */
    459491    public boolean isActiveLayerVisible() {
    460         synchronized (layers) {
     492        layerLock.readLock().lock();
     493        try {
    461494            return isActiveLayerDrawable() && editLayer.isVisible();
     495        } finally {
     496            layerLock.readLock().unlock();
    462497        }
    463498    }
    464499
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    499534        Layer oldActiveLayer = activeLayer;
    500535        OsmDataLayer oldEditLayer = editLayer;
    501536
    502         synchronized (layers) {
    503             List<Layer> layersList = new ArrayList<>(layers);
     537        layerLock.writeLock().lock();
     538        layerLock.readLock().lock();
     539        try {
     540            try {
     541                List<Layer> layersList = new ArrayList<>(layers);
    504542
    505             if (!layersList.remove(layer))
    506                 return;
     543                if (!layersList.remove(layer))
     544                    return;
    507545
    508             listenersToFire = setEditLayer(layersList);
     546                listenersToFire = setEditLayer(layersList);
    509547
    510             if (layer == activeLayer) {
    511                 listenersToFire.addAll(setActiveLayer(determineNextActiveLayer(layersList), false));
    512             }
     548                if (layer == activeLayer) {
     549                    listenersToFire.addAll(setActiveLayer(determineNextActiveLayer(layersList), false));
     550                }
    513551
    514             if (layer instanceof OsmDataLayer) {
    515                 ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this);
    516             }
     552                if (layer instanceof OsmDataLayer) {
     553                    ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this);
     554                }
    517555
    518             layers.remove(layer);
    519             Main.removeProjectionChangeListener(layer);
     556                layers.remove(layer);
     557                Main.removeProjectionChangeListener(layer);
    520558
     559            } finally {
     560                layerLock.writeLock().unlock();
     561            }
    521562            onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire);
    522563            fireLayerRemoved(layer);
    523564            layer.removePropertyChangeListener(this);
    524565            layer.destroy();
    525566            AudioPlayer.reset();
     567        } finally {
     568            layerLock.readLock().unlock();
    526569        }
    527570        repaint();
    528571    }
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    562605        Layer oldActiveLayer = activeLayer;
    563606        OsmDataLayer oldEditLayer = editLayer;
    564607
    565         synchronized (layers) {
    566             int curLayerPos = layers.indexOf(layer);
    567             if (curLayerPos == -1)
    568                 throw new IllegalArgumentException(tr("Layer not in list."));
    569             if (pos == curLayerPos)
    570                 return; // already in place.
    571             layers.remove(curLayerPos);
    572             if (pos >= layers.size()) {
    573                 layers.add(layer);
    574             } else {
    575                 layers.add(pos, layer);
     608        layerLock.writeLock().lock();
     609        layerLock.readLock().lock();
     610        try {
     611            try {
     612                int curLayerPos = layers.indexOf(layer);
     613                if (curLayerPos == -1)
     614                    throw new IllegalArgumentException(tr("Layer not in list."));
     615                if (pos == curLayerPos)
     616                    return; // already in place.
     617                layers.remove(curLayerPos);
     618                if (pos >= layers.size()) {
     619                    layers.add(layer);
     620                } else {
     621                    layers.add(pos, layer);
     622                }
     623                listenersToFire = setEditLayer(layers);
     624            } finally {
     625                layerLock.writeLock().unlock();
    576626            }
    577             listenersToFire = setEditLayer(layers);
    578627            onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire);
    579628            AudioPlayer.reset();
     629        } finally {
     630            layerLock.readLock().unlock();
    580631        }
    581632        repaint();
    582633    }
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    589640     */
    590641    public int getLayerPos(Layer layer) {
    591642        int curLayerPos;
    592         synchronized (layers) {
     643        layerLock.readLock().lock();
     644        try {
    593645            curLayerPos = layers.indexOf(layer);
     646        } finally {
     647            layerLock.readLock().unlock();
    594648        }
    595649        if (curLayerPos == -1)
    596650            throw new IllegalArgumentException(tr("Layer not in list."));
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    607661     * first, layer with the highest Z-Order last.
    608662     */
    609663    public List<Layer> getVisibleLayersInZOrder() {
    610         synchronized (layers) {
     664        layerLock.readLock().lock();
     665        try {
    611666            List<Layer> ret = new ArrayList<>();
    612667            // This is set while we delay the addition of the active layer.
    613668            boolean activeLayerDelayed = false;
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    632687                ret.add(activeLayer);
    633688            }
    634689            return ret;
     690        } finally {
     691            layerLock.readLock().unlock();
    635692        }
    636693    }
    637694
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    820877     * @return An unmodifiable collection of all layers
    821878     */
    822879    public Collection<Layer> getAllLayers() {
    823         synchronized (layers) {
     880        layerLock.readLock().lock();
     881        try {
    824882            return Collections.unmodifiableCollection(new ArrayList<>(layers));
     883        } finally {
     884            layerLock.readLock().unlock();
    825885        }
    826886    }
    827887
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    829889     * @return An unmodifiable ordered list of all layers
    830890     */
    831891    public List<Layer> getAllLayersAsList() {
    832         synchronized (layers) {
     892        layerLock.readLock().lock();
     893        try {
    833894            return Collections.unmodifiableList(new ArrayList<>(layers));
     895        } finally {
     896            layerLock.readLock().unlock();
    834897        }
    835898    }
    836899
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    855918     * @return the number of layers managed by this map view
    856919     */
    857920    public int getNumLayers() {
    858         synchronized (layers) {
     921        layerLock.readLock().lock();
     922        try {
    859923            return layers.size();
     924        } finally {
     925            layerLock.readLock().unlock();
    860926        }
    861927    }
    862928
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    920986     * @throws IllegalArgumentException if layer is not in the lis of layers
    921987     */
    922988    public void setActiveLayer(Layer layer) {
     989        layerLock.writeLock().lock();
     990        layerLock.readLock().lock();
    923991        EnumSet<LayerListenerType> listenersToFire;
    924 
    925         synchronized (layers) {
    926             Layer oldActiveLayer = activeLayer;
    927             OsmDataLayer oldEditLayer = editLayer;
    928             listenersToFire = setActiveLayer(layer, true);
     992        Layer oldActiveLayer = activeLayer;
     993        OsmDataLayer oldEditLayer = editLayer;
     994        try {
     995            try {
     996                listenersToFire = setActiveLayer(layer, true);
     997            } finally {
     998                layerLock.writeLock().unlock();
     999            }
    9291000            onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire);
     1001        } finally {
     1002            layerLock.readLock().unlock();
    9301003        }
    9311004        repaint();
    9321005    }
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    9591032     * @return the currently active layer (may be null)
    9601033     */
    9611034    public Layer getActiveLayer() {
    962         synchronized (layers) {
     1035        layerLock.readLock().lock();
     1036        try {
    9631037            return activeLayer;
     1038        } finally {
     1039            layerLock.readLock().unlock();
    9641040        }
    9651041    }
    9661042
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    10151091     * @return the current edit layer. May be null.
    10161092     */
    10171093    public OsmDataLayer getEditLayer() {
    1018         synchronized (layers) {
     1094        layerLock.readLock().lock();
     1095        try {
    10191096            return editLayer;
     1097        } finally {
     1098            layerLock.readLock().unlock();
    10201099        }
    10211100    }
    10221101
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    10271106     * @return true if the list of layers managed by this map view contain layer
    10281107     */
    10291108    public boolean hasLayer(Layer layer) {
    1030         synchronized (layers) {
     1109        layerLock.readLock().lock();
     1110        try {
    10311111            return layers.contains(layer);
     1112        } finally {
     1113            layerLock.readLock().unlock();
    10321114        }
    10331115    }
    10341116
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    10931175     */
    10941176    protected void refreshTitle() {
    10951177        if (Main.parent != null) {
    1096             synchronized (layers) {
     1178            layerLock.readLock().lock();
     1179            try {
    10971180                boolean dirty = editLayer != null &&
    10981181                        (editLayer.requiresSaveToFile() || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged()));
    10991182                ((JFrame) Main.parent).setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor"));
    11001183                ((JFrame) Main.parent).getRootPane().putClientProperty("Window.documentModified", dirty);
     1184            } finally {
     1185                layerLock.readLock().unlock();
    11011186            }
    11021187        }
    11031188    }
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    11231208        if (mapMover != null) {
    11241209            mapMover.destroy();
    11251210        }
    1126         synchronized (layers) {
     1211        layerLock.writeLock().lock();
     1212        try {
    11271213            activeLayer = null;
    11281214            changedLayer = null;
    11291215            editLayer = null;
    11301216            layers.clear();
    1131             nonChangedLayers.clear();
     1217        } finally {
     1218            layerLock.writeLock().unlock();
    11321219        }
     1220        nonChangedLayers.clear();
    11331221        synchronized (temporaryLayers) {
    11341222            temporaryLayers.clear();
    11351223        }