Răsfoiți Sursa

* 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

Sha..rd 13 ani în urmă
părinte
comite
0751d9ff76

+ 40 - 8
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){
     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>

+ 16 - 1
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.
  * 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

+ 3 - 0
engine/src/core/com/jme3/asset/cache/SimpleAssetCache.java

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

+ 9 - 5
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.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() {
     }
     }
 }
 }

+ 6 - 1
engine/src/core/com/jme3/asset/cache/WeakRefCloneAssetCache.java

@@ -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;