--- old/modules/javafx.graphics/src/main/java/javafx/scene/shape/PredefinedMeshManager.java 2017-12-22 21:14:25.754471352 +0530 +++ new/modules/javafx.graphics/src/main/java/javafx/scene/shape/PredefinedMeshManager.java 2017-12-22 21:14:25.522355352 +0530 @@ -1,5 +1,5 @@ /* - * 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 @@ -25,17 +25,75 @@ 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 boxCache = null; - private HashMap sphereCache = null; - private HashMap cylinderCache = null; + private static class TriangleMeshCache { + HashMap> 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(mesh)); + } + } + + private void cleanCache() { + Integer[] entriesToRemove = new Integer[cache.size()]; + int count = 0; + for (HashMap.Entry> 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() {} @@ -90,40 +148,19 @@ 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); } } @@ -143,37 +180,33 @@ // 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 - INSTANCE = new HashMap(INITAL_CAPACITY, LOAD_FACTOR); + private static final TriangleMeshCache INSTANCE = new TriangleMeshCache(); } private final static class SphereCacheLoader { // lazy & thread-safe instantiation - private static final HashMap - INSTANCE = new HashMap(INITAL_CAPACITY, LOAD_FACTOR); + private static final TriangleMeshCache INSTANCE = new TriangleMeshCache(); } private final static class CylinderCacheLoader { // lazy & thread-safe instantiation - private static final HashMap - INSTANCE = new HashMap(INITAL_CAPACITY, LOAD_FACTOR); + private static final TriangleMeshCache INSTANCE = new TriangleMeshCache(); } - };