From 0751d9ff7689c6453eb9cde4c1ff0b010eacbc59 Mon Sep 17 00:00:00 2001 From: "Sha..rd" Date: Sun, 15 Apr 2012 18:30:04 +0000 Subject: [PATCH] * Added methods to DesktopAssetManager: addToCache/getFromCache/deleteFromCache/clearCache * Added new method to AssetCache interface to specify that registerAssetClone() won't be used (for the methods used above) git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9318 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../com/jme3/asset/DesktopAssetManager.java | 48 +++++++++++++++---- .../core/com/jme3/asset/cache/AssetCache.java | 17 ++++++- .../jme3/asset/cache/SimpleAssetCache.java | 3 ++ .../jme3/asset/cache/WeakRefAssetCache.java | 14 ++++-- .../asset/cache/WeakRefCloneAssetCache.java | 7 ++- 5 files changed, 74 insertions(+), 15 deletions(-) diff --git a/engine/src/core/com/jme3/asset/DesktopAssetManager.java b/engine/src/core/com/jme3/asset/DesktopAssetManager.java index 1b31bd75d..3a2cd9f59 100644 --- a/engine/src/core/com/jme3/asset/DesktopAssetManager.java +++ b/engine/src/core/com/jme3/asset/DesktopAssetManager.java @@ -193,21 +193,53 @@ public class DesktopAssetManager implements AssetManager { } } - public void clearCache(){ - handler.clearCache(); - if (logger.isLoggable(Level.FINER)){ - logger.log(Level.FINER, "All asset caches cleared."); - } - } - public AssetInfo locateAsset(AssetKey key){ AssetInfo info = handler.tryLocate(key); if (info == null){ logger.log(Level.WARNING, "Cannot locate resource: {0}", key); } - return info; } + + public T getFromCache(AssetKey key) { + AssetCache cache = handler.getCache(key.getCacheType()); + if (cache != null) { + T asset = cache.getFromCache(key); + if (asset != null) { + // Since getFromCache fills the load stack, it has to be popped + cache.notifyNoAssetClone(); + } + return asset; + } else { + throw new IllegalArgumentException("Key " + key + " specifies no cache."); + } + } + + public void addToCache(AssetKey key, T asset) { + AssetCache cache = handler.getCache(key.getCacheType()); + if (cache != null) { + cache.addToCache(key, asset); + cache.notifyNoAssetClone(); + } else { + throw new IllegalArgumentException("Key " + key + " specifies no cache."); + } + } + + public boolean deleteFromCache(AssetKey key) { + AssetCache cache = handler.getCache(key.getCacheType()); + if (cache != null) { + return cache.deleteFromCache(key); + } else { + throw new IllegalArgumentException("Key " + key + " specifies no cache."); + } + } + + public void clearCache(){ + handler.clearCache(); + if (logger.isLoggable(Level.FINER)){ + logger.log(Level.FINER, "All asset caches cleared."); + } + } /** * Thread-safe. diff --git a/engine/src/core/com/jme3/asset/cache/AssetCache.java b/engine/src/core/com/jme3/asset/cache/AssetCache.java index 916ab33c7..db7675419 100644 --- a/engine/src/core/com/jme3/asset/cache/AssetCache.java +++ b/engine/src/core/com/jme3/asset/cache/AssetCache.java @@ -10,7 +10,13 @@ import com.jme3.asset.AssetKey; * caching method can be selected that is most appropriate for that asset type. * The asset cache must be thread safe. *

- * + * Some caches are used to manage cloneable assets, which track reachability + * based on a shared key in all instances exposed in user code. + * E.g. {@link WeakRefCloneAssetCache} uses this approach. + * For those particular caches, either {@link #registerAssetClone(com.jme3.asset.AssetKey, java.lang.Object) } + * or {@link #notifyNoAssetClone() } MUST be called to avoid memory + * leaking following a successful {@link #addToCache(com.jme3.asset.AssetKey, java.lang.Object) } + * or {@link #getFromCache(com.jme3.asset.AssetKey) } call! * * @author Kirill Vainer */ @@ -43,6 +49,15 @@ public interface AssetCache { */ public void registerAssetClone(AssetKey key, T clone); + /** + * Notifies the cache that even though the methods {@link #addToCache(com.jme3.asset.AssetKey, java.lang.Object) } + * or {@link #getFromCache(com.jme3.asset.AssetKey) } were used, there won't + * be a call to {@link #registerAssetClone(com.jme3.asset.AssetKey, java.lang.Object) } + * for some reason. For example, if an error occurred during loading + * or if the addToCache/getFromCache were used from user code. + */ + public void notifyNoAssetClone(); + /** * Retrieves an asset from the cache. * It is possible to add an asset to the cache using diff --git a/engine/src/core/com/jme3/asset/cache/SimpleAssetCache.java b/engine/src/core/com/jme3/asset/cache/SimpleAssetCache.java index 0935704cf..ccd4f5baa 100644 --- a/engine/src/core/com/jme3/asset/cache/SimpleAssetCache.java +++ b/engine/src/core/com/jme3/asset/cache/SimpleAssetCache.java @@ -37,5 +37,8 @@ public class SimpleAssetCache implements AssetCache { public void clearCache() { keyToAssetMap.clear(); } + + public void notifyNoAssetClone() { + } } diff --git a/engine/src/core/com/jme3/asset/cache/WeakRefAssetCache.java b/engine/src/core/com/jme3/asset/cache/WeakRefAssetCache.java index 53b63a720..20d8c169e 100644 --- a/engine/src/core/com/jme3/asset/cache/WeakRefAssetCache.java +++ b/engine/src/core/com/jme3/asset/cache/WeakRefAssetCache.java @@ -5,6 +5,8 @@ import com.jme3.asset.AssetProcessor; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; /** * A garbage collector bound asset cache that handles non-clonable objects. @@ -20,11 +22,13 @@ import java.util.concurrent.ConcurrentHashMap; */ public class WeakRefAssetCache implements AssetCache { + private static final Logger logger = Logger.getLogger(WeakRefAssetCache.class.getName()); + private final ReferenceQueue refQueue = new ReferenceQueue(); private final ConcurrentHashMap assetCache = new ConcurrentHashMap(); - + private static class AssetRef extends WeakReference { private final AssetKey assetKey; @@ -46,7 +50,7 @@ public class WeakRefAssetCache implements AssetCache { } } if (removedAssets >= 1) { -// System.out.println("WeakRefAssetCache: " + removedAssets + " assets were purged from the cache."); + logger.log(Level.INFO, "WeakRefAssetCache: {0} assets were purged from the cache.", removedAssets); } } @@ -81,8 +85,8 @@ public class WeakRefAssetCache implements AssetCache { } public void registerAssetClone(AssetKey key, T clone) { -// Texture t = (Texture) clone; -// System.out.println("clonable asset " + System.identityHashCode(t.getImage())); - //throw new UnsupportedOperationException("Cannot use this cache for cloneable assets"); + } + + public void notifyNoAssetClone() { } } diff --git a/engine/src/core/com/jme3/asset/cache/WeakRefCloneAssetCache.java b/engine/src/core/com/jme3/asset/cache/WeakRefCloneAssetCache.java index d99d2ff9c..673ae73c7 100644 --- a/engine/src/core/com/jme3/asset/cache/WeakRefCloneAssetCache.java +++ b/engine/src/core/com/jme3/asset/cache/WeakRefCloneAssetCache.java @@ -1,7 +1,7 @@ package com.jme3.asset.cache; -import com.jme3.asset.CloneableSmartAsset; import com.jme3.asset.AssetKey; +import com.jme3.asset.CloneableSmartAsset; import java.lang.ref.WeakReference; import java.util.ArrayDeque; import java.util.WeakHashMap; @@ -61,6 +61,11 @@ public class WeakRefCloneAssetCache implements AssetCache { ArrayDeque loadStack = assetLoadStack.get(); ((CloneableSmartAsset)clone).setKey(loadStack.pop()); } + + public void notifyNoAssetClone() { + ArrayDeque loadStack = assetLoadStack.get(); + loadStack.pop(); + } public T getFromCache(AssetKey key) { SmartCachedAsset smartInfo;