Ignore:
Timestamp:
2016-09-17T16:44:15+02:00 (8 years ago)
Author:
michael2402
Message:

Change LayerManager#getLayers() to not require a lock any more. Fixes #13644

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/LayerManager.java

    r10999 r11011  
    1010import java.util.Set;
    1111import java.util.concurrent.CopyOnWriteArrayList;
     12import java.util.function.Consumer;
    1213
    1314import org.openstreetmap.josm.Main;
     
    170171
    171172    /**
    172      * This is the list of layers we manage.
    173      */
    174     private final List<Layer> layers = new ArrayList<>();
     173     * This is the list of layers we manage. The list is unmodifyable It is only changed in the EDT.
     174     * @see LayerManager#updateLayers(Consumer)
     175     */
     176    private volatile List<Layer> layers = Collections.emptyList();
    175177
    176178    private final List<LayerChangeListener> layerChangeListeners = new CopyOnWriteArrayList<>();
     
    228230
    229231    protected Collection<Layer> realRemoveSingleLayer(Layer layerToRemove) {
    230         layers.remove(layerToRemove);
     232        updateLayers(mutableLayers -> mutableLayers.remove(layerToRemove));
    231233        return fireLayerRemoving(layerToRemove);
    232234    }
     
    248250        checkPosition(position);
    249251
    250         int curLayerPos = layers.indexOf(layer);
     252        int curLayerPos = getLayers().indexOf(layer);
    251253        if (position == curLayerPos)
    252254            return; // already in place.
    253         layers.remove(curLayerPos);
    254         insertLayerAt(layer, position);
     255        // update needs to be done in one run
     256        updateLayers(mutableLayers -> {
     257            mutableLayers.remove(curLayerPos);
     258            insertLayerAt(mutableLayers, layer, position);
     259        });
    255260        fireLayerOrderChanged();
    256261    }
     
    262267     */
    263268    private void insertLayerAt(Layer layer, int position) {
     269        updateLayers(mutableLayers -> insertLayerAt(mutableLayers, layer, position));
     270    }
     271
     272    private static void insertLayerAt(List<Layer> layers, Layer layer, int position) {
    264273        if (position == layers.size()) {
    265274            layers.add(layer);
     
    275284     */
    276285    private void checkPosition(int position) {
    277         if (position < 0 || position > layers.size()) {
     286        if (position < 0 || position > getLayers().size()) {
    278287            throw new IndexOutOfBoundsException("Position " + position + " out of range.");
    279288        }
     289    }
     290
     291    /**
     292     * Update the {@link #layers} field. This method should be used instead of a direct field access.
     293     * @param mutator A method that gets the writable list of layers and should modify it.
     294     */
     295    private void updateLayers(Consumer<List<Layer>> mutator) {
     296        GuiHelper.assertCallFromEdt();
     297        ArrayList<Layer> newLayers = new ArrayList<>(getLayers());
     298        mutator.accept(newLayers);
     299        layers = Collections.unmodifiableList(newLayers);
    280300    }
    281301
     
    284304     * @return The list of layers.
    285305     */
    286     public synchronized List<Layer> getLayers() {
    287         return Collections.unmodifiableList(new ArrayList<>(layers));
     306    public List<Layer> getLayers() {
     307        return layers;
    288308    }
    289309
     
    299319     * @return an unmodifiable list of layers of a certain type.
    300320     */
    301     public synchronized <T extends Layer> List<T> getLayersOfType(Class<T> ofType) {
     321    public <T extends Layer> List<T> getLayersOfType(Class<T> ofType) {
    302322        return new ArrayList<>(Utils.filteredCollection(getLayers(), ofType));
    303323    }
     
    309329     * @return true if the list of layers managed by this map view contain layer
    310330     */
    311     public synchronized boolean containsLayer(Layer layer) {
    312         return layers.contains(layer);
     331    public boolean containsLayer(Layer layer) {
     332        return getLayers().contains(layer);
    313333    }
    314334
Note: See TracChangeset for help on using the changeset viewer.