< prev index next >

modules/javafx.graphics/src/main/java/javafx/scene/shape/PredefinedMeshManager.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -23,21 +23,79 @@
  * questions.
  */
 
 package javafx.scene.shape;
 
+import java.lang.ref.SoftReference;
 import java.util.HashMap;
 
 final class PredefinedMeshManager {
-
-    private static final PredefinedMeshManager INSTANCE = new PredefinedMeshManager();
     private static final int INITAL_CAPACITY = 17; // TODO
     private static final float LOAD_FACTOR = 0.75f;
 
-    private HashMap<Integer, TriangleMesh> boxCache = null;
-    private HashMap<Integer, TriangleMesh> sphereCache = null;
-    private HashMap<Integer, TriangleMesh> cylinderCache = null;
+    private static class TriangleMeshCache {
+        HashMap<Integer, SoftReference<TriangleMesh>> cache = new HashMap<>(INITAL_CAPACITY, LOAD_FACTOR);
+
+        private TriangleMesh get(Integer key) {
+            cleanCache();
+            return (cache.containsKey(key))? cache.get(key).get() : null;
+        }
+
+        private void put(Integer key, TriangleMesh mesh) {
+            cleanCache();
+            if (mesh != null) {
+                cache.put(key, new SoftReference<TriangleMesh>(mesh));
+            }
+        }
+
+        private void cleanCache() {
+            Integer[] entriesToRemove = new Integer[cache.size()];
+            int count = 0;
+            for (HashMap.Entry<Integer, SoftReference<TriangleMesh>> entry : cache.entrySet()) {
+                if (entry.getValue().get() == null) {
+                    entriesToRemove[count++] = entry.getKey();
+                }
+            }
+            for (int i = 0; i < count; ++i) {
+                cache.remove(entriesToRemove[i]);
+            }
+        }
+
+        private void clear() {
+            cache.clear();
+        }
+
+        private int size() {
+            cleanCache();
+            return cache.size();
+        }
+
+        // for testing purpose
+        private void printState(String name) {
+            System.out.println(name + " size:    " + size());
+        }
+
+        private void invalidateMesh(Integer key) {
+            if (cache.containsKey(key)) {
+                TriangleMesh mesh = cache.get(key).get();
+                if (mesh != null) {
+                    mesh.decRef();
+                    int count = mesh.getRefCount();
+                    if (count == 0) {
+                        cache.remove(key);
+                    }
+                } else {
+                    cache.remove(key);
+                }
+            }
+        }
+    }
+
+    private static final PredefinedMeshManager INSTANCE = new PredefinedMeshManager();
+    private TriangleMeshCache boxCache = null;
+    private TriangleMeshCache sphereCache = null;
+    private TriangleMeshCache cylinderCache = null;
 
     private PredefinedMeshManager() {}
 
     static PredefinedMeshManager getInstance() {
         return INSTANCE;

@@ -88,44 +146,23 @@
         return mesh;
     }
 
     synchronized void invalidateBoxMesh(int key) {
         if (boxCache != null) {
-            TriangleMesh mesh = boxCache.get(key);
-            if (mesh != null) {
-                mesh.decRef();
-                int count = mesh.getRefCount();
-                if (count == 0) {
-                    boxCache.remove(key);
-                }
-            }
+            boxCache.invalidateMesh(key);
         }
     }
 
     synchronized void invalidateSphereMesh(int key) {
         if (sphereCache != null) {
-            TriangleMesh mesh = sphereCache.get(key);
-            if (mesh != null) {
-                mesh.decRef();
-                int count = mesh.getRefCount();
-                if (count == 0) {
-                    sphereCache.remove(key);
-                }
-            }
+            sphereCache.invalidateMesh(key);
         }
     }
 
     synchronized void invalidateCylinderMesh(int key) {
         if (cylinderCache != null) {
-            TriangleMesh mesh = cylinderCache.get(key);
-            if (mesh != null) {
-                mesh.decRef();
-                int count = mesh.getRefCount();
-                if (count == 0) {
-                    cylinderCache.remove(key);
-                }
-            }
+            cylinderCache.invalidateMesh(key);
         }
     }
 
     synchronized void dispose() {
         // just clearing references to them

@@ -141,39 +178,35 @@
     }
 
     // for testing purpose
     synchronized void printStats() {
         if (boxCache != null) {
-            System.out.println("BoxCache size:  " +  boxCache.size());
+            boxCache.printState("BoxCache");
         }
 
         if (sphereCache != null) {
-            System.out.println("SphereCache size:    " + sphereCache.size());
+            sphereCache.printState("SphereCache");
         }
 
         if (cylinderCache != null) {
-            System.out.println("CylinderCache size:    " + cylinderCache.size());
+            cylinderCache.printState("CylinderCache");
         }
     }
 
     private final static class BoxCacheLoader {
 
         // lazy & thread-safe instantiation
-        private static final HashMap<Integer, TriangleMesh>
-                INSTANCE = new HashMap<Integer, TriangleMesh>(INITAL_CAPACITY, LOAD_FACTOR);
+        private static final TriangleMeshCache INSTANCE = new TriangleMeshCache();
     }
 
     private final static class SphereCacheLoader {
 
         // lazy & thread-safe instantiation
-        private static final HashMap<Integer, TriangleMesh>
-                INSTANCE = new HashMap<Integer, TriangleMesh>(INITAL_CAPACITY, LOAD_FACTOR);
+        private static final TriangleMeshCache INSTANCE = new TriangleMeshCache();
     }
 
     private final static class CylinderCacheLoader {
 
         // lazy & thread-safe instantiation
-        private static final HashMap<Integer, TriangleMesh>
-                INSTANCE = new HashMap<Integer, TriangleMesh>(INITAL_CAPACITY, LOAD_FACTOR);
+        private static final TriangleMeshCache INSTANCE = new TriangleMeshCache();
     }
-
 };
< prev index next >