* 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
3.0
Sha..rd 13 years ago
parent c8fa79fbd6
commit 0751d9ff76
  1. 48
      engine/src/core/com/jme3/asset/DesktopAssetManager.java
  2. 17
      engine/src/core/com/jme3/asset/cache/AssetCache.java
  3. 3
      engine/src/core/com/jme3/asset/cache/SimpleAssetCache.java
  4. 14
      engine/src/core/com/jme3/asset/cache/WeakRefAssetCache.java
  5. 7
      engine/src/core/com/jme3/asset/cache/WeakRefCloneAssetCache.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){ public AssetInfo locateAsset(AssetKey<?> key){
AssetInfo info = handler.tryLocate(key); AssetInfo info = handler.tryLocate(key);
if (info == null){ if (info == null){
logger.log(Level.WARNING, "Cannot locate resource: {0}", key); logger.log(Level.WARNING, "Cannot locate resource: {0}", key);
} }
return info; return info;
} }
public <T> T getFromCache(AssetKey<T> 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 <T> void addToCache(AssetKey<T> 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 <T> boolean deleteFromCache(AssetKey<T> 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.");
}
}
/** /**
* <font color="red">Thread-safe.</font> * <font color="red">Thread-safe.</font>

@ -10,7 +10,13 @@ import com.jme3.asset.AssetKey;
* caching method can be selected that is most appropriate for that asset type. * caching method can be selected that is most appropriate for that asset type.
* The asset cache must be thread safe. * The asset cache must be thread safe.
* <p> * <p>
* * 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() } <b>MUST</b> 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 * @author Kirill Vainer
*/ */
@ -43,6 +49,15 @@ public interface AssetCache {
*/ */
public <T> void registerAssetClone(AssetKey<T> key, T clone); public <T> void registerAssetClone(AssetKey<T> 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. * Retrieves an asset from the cache.
* It is possible to add an asset to the cache using * It is possible to add an asset to the cache using

@ -37,5 +37,8 @@ public class SimpleAssetCache implements AssetCache {
public void clearCache() { public void clearCache() {
keyToAssetMap.clear(); keyToAssetMap.clear();
} }
public void notifyNoAssetClone() {
}
} }

@ -5,6 +5,8 @@ import com.jme3.asset.AssetProcessor;
import java.lang.ref.ReferenceQueue; import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentHashMap; 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. * 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 { public class WeakRefAssetCache implements AssetCache {
private static final Logger logger = Logger.getLogger(WeakRefAssetCache.class.getName());
private final ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); private final ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
private final ConcurrentHashMap<AssetKey, AssetRef> assetCache private final ConcurrentHashMap<AssetKey, AssetRef> assetCache
= new ConcurrentHashMap<AssetKey, AssetRef>(); = new ConcurrentHashMap<AssetKey, AssetRef>();
private static class AssetRef extends WeakReference<Object> { private static class AssetRef extends WeakReference<Object> {
private final AssetKey assetKey; private final AssetKey assetKey;
@ -46,7 +50,7 @@ public class WeakRefAssetCache implements AssetCache {
} }
} }
if (removedAssets >= 1) { 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 <T> void registerAssetClone(AssetKey<T> key, T clone) { public <T> void registerAssetClone(AssetKey<T> 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() {
} }
} }

@ -1,7 +1,7 @@
package com.jme3.asset.cache; package com.jme3.asset.cache;
import com.jme3.asset.CloneableSmartAsset;
import com.jme3.asset.AssetKey; import com.jme3.asset.AssetKey;
import com.jme3.asset.CloneableSmartAsset;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@ -61,6 +61,11 @@ public class WeakRefCloneAssetCache implements AssetCache {
ArrayDeque<AssetKey> loadStack = assetLoadStack.get(); ArrayDeque<AssetKey> loadStack = assetLoadStack.get();
((CloneableSmartAsset)clone).setKey(loadStack.pop()); ((CloneableSmartAsset)clone).setKey(loadStack.pop());
} }
public void notifyNoAssetClone() {
ArrayDeque<AssetKey> loadStack = assetLoadStack.get();
loadStack.pop();
}
public <T> T getFromCache(AssetKey<T> key) { public <T> T getFromCache(AssetKey<T> key) {
SmartCachedAsset smartInfo; SmartCachedAsset smartInfo;

Loading…
Cancel
Save