* 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. 12
      engine/src/core/com/jme3/asset/cache/WeakRefAssetCache.java
  5. 7
      engine/src/core/com/jme3/asset/cache/WeakRefCloneAssetCache.java

@ -193,22 +193,54 @@ 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> 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>
*

@ -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.
* <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
*/
@ -43,6 +49,15 @@ public interface AssetCache {
*/
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.
* It is possible to add an asset to the cache using

@ -38,4 +38,7 @@ public class SimpleAssetCache implements AssetCache {
keyToAssetMap.clear();
}
public void notifyNoAssetClone() {
}
}

@ -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,6 +22,8 @@ import java.util.concurrent.ConcurrentHashMap;
*/
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 ConcurrentHashMap<AssetKey, AssetRef> assetCache
@ -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 <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;
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;
@ -62,6 +62,11 @@ public class WeakRefCloneAssetCache implements AssetCache {
((CloneableSmartAsset)clone).setKey(loadStack.pop());
}
public void notifyNoAssetClone() {
ArrayDeque<AssetKey> loadStack = assetLoadStack.get();
loadStack.pop();
}
public <T> T getFromCache(AssetKey<T> key) {
SmartCachedAsset smartInfo;
synchronized (smartCache){

Loading…
Cancel
Save