Ignore:
Timestamp:
2011-06-07T19:05:14+02:00 (13 years ago)
Author:
bastiK
Message:

memory optimizations for Node & WayPoint (Patch by Gubaer, modified)

The field 'proj' in CachedLatLon is a waste of memory. For the 2 classes where this has the greatest impact, the cache for the projected coordinates is replaced by 2 simple double fields (east & north). On projection change, they have to be invalidated explicitly. This is handled by the DataSet & the GpxLayer.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/Main.java

    r3993 r4126  
    1616import java.awt.event.WindowEvent;
    1717import java.io.File;
     18import java.lang.ref.WeakReference;
    1819import java.net.URI;
    1920import java.net.URISyntaxException;
    2021import java.util.ArrayList;
    2122import java.util.Collection;
     23import java.util.Iterator;
    2224import java.util.List;
    2325import java.util.Map;
     
    5658import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy;
    5759import org.openstreetmap.josm.data.projection.Projection;
     60import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
    5861import org.openstreetmap.josm.data.validation.OsmValidator;
    5962import org.openstreetmap.josm.gui.GettingStarted;
     
    7376import org.openstreetmap.josm.io.OsmApi;
    7477import org.openstreetmap.josm.plugins.PluginHandler;
     78import org.openstreetmap.josm.tools.CheckParameterUtil;
    7579import org.openstreetmap.josm.tools.I18n;
    7680import org.openstreetmap.josm.tools.ImageProvider;
     
    119123    public static PrimitiveDeepCopy pasteBuffer = new PrimitiveDeepCopy();
    120124    public static Layer pasteSource;
    121     /**
    122      * The projection method used.
    123      */
    124     public static Projection proj;
     125
    125126    /**
    126127     * The MapFrame. Use setMapFrame to set or clear it.
     
    154155     */
    155156    static public int debug_level = 1;
    156     static public final void debug(String msg) {
     157    static public void debug(String msg) {
    157158        if (debug_level <= 0)
    158159            return;
     
    213214        platform.startupHook();
    214215
    215         // We try to establish an API connection early, so that any API 
     216        // We try to establish an API connection early, so that any API
    216217        // capabilities are already known to the editor instance. However
    217218        // if it goes wrong that's not critical at this stage.
     
    768769        System.err.println("Error: Could not recognize Java Version: "+version);
    769770    }
     771
     772    /* ----------------------------------------------------------------------------------------- */
     773    /* projection handling  - Main is a registry for a single, global projection instance        */
     774    /*                                                                                           */
     775    /* TODO: For historical reasons the registry is implemented by Main. An alternative approach */
     776    /* would be a singleton org.openstreetmap.josm.data.projection.ProjectionRegistry class.     */
     777    /* ----------------------------------------------------------------------------------------- */
     778    /**
     779     * The projection method used.
     780     * @deprecated use {@link #getProjection()} and {@link #setProjection(Projection)} instead.
     781     * For the time being still publicly available, but avoid/migrate write access to it. Use
     782     * {@link #setProjection(Projection)} in order to trigger a projection change event.
     783     */
     784    @Deprecated
     785    public static Projection proj;
     786
     787    /**
     788     * Replies the current projection.
     789     *
     790     * @return
     791     */
     792    public static Projection getProjection() {
     793        return proj;
     794    }
     795
     796    /**
     797     * Sets the current projection
     798     *
     799     * @param p the projection
     800     */
     801    public static void setProjection(Projection p) {
     802        CheckParameterUtil.ensureParameterNotNull(p);
     803        Projection oldValue = proj;
     804        proj = p;
     805        fireProjectionChanged(oldValue, proj);
     806    }
     807
     808    /*
     809     * Keep WeakReferences to the listeners. This relieves clients from the burden of
     810     * explicitly removing the listeners and allows us to transparently register every
     811     * created dataset as projection change listener.
     812     */
     813    private static final ArrayList<WeakReference<ProjectionChangeListener>> listeners = new ArrayList<WeakReference<ProjectionChangeListener>>();
     814
     815    private static void fireProjectionChanged(Projection oldValue, Projection newValue) {
     816        if (newValue == null ^ oldValue == null
     817                || (newValue != null && oldValue != null && !newValue.getClass().getName().equals(oldValue.getClass().getName()))) {
     818
     819            synchronized(Main.class) {
     820                Iterator<WeakReference<ProjectionChangeListener>> it = listeners.iterator();
     821                while(it.hasNext()){
     822                    WeakReference<ProjectionChangeListener> wr = it.next();
     823                    if (wr.get() == null) {
     824                        it.remove();
     825                        continue;
     826                    }
     827                    wr.get().projectionChanged(oldValue, newValue);
     828                }
     829            }
     830            if (newValue != null) {
     831                Bounds b = (Main.map != null && Main.map.mapView != null) ? Main.map.mapView.getRealBounds() : null;
     832                if (b != null){
     833                    Main.map.mapView.zoomTo(b);
     834                }
     835            }
     836            /* TODO - remove layers with fixed projection */
     837        }
     838    }
     839
     840    /**
     841     * Register a projection change listener
     842     *
     843     * @param listener the listener. Ignored if null.
     844     */
     845    public static void addProjectionChangeListener(ProjectionChangeListener listener) {
     846        if (listener == null) return;
     847        synchronized (Main.class) {
     848            for (WeakReference<ProjectionChangeListener> wr : listeners) {
     849                // already registered ? => abort
     850                if (wr.get() == listener) return;
     851            }
     852        }
     853        listeners.add(new WeakReference<ProjectionChangeListener>(listener));
     854    }
     855
     856    /**
     857     * Removes a projection change listener
     858     *
     859     * @param listener the listener. Ignored if null.
     860     */
     861    public static void removeProjectionChangeListener(ProjectionChangeListener listener) {
     862        if (listener == null) return;
     863        synchronized(Main.class){
     864            Iterator<WeakReference<ProjectionChangeListener>> it = listeners.iterator();
     865            while(it.hasNext()){
     866                WeakReference<ProjectionChangeListener> wr = it.next();
     867                // remove the listener - and any other listener which god garbage
     868                // collected in the meantime
     869                if (wr.get() == null || wr.get() == listener) {
     870                    it.remove();
     871                }
     872            }
     873        }
     874    }
    770875}
Note: See TracChangeset for help on using the changeset viewer.