public void changeWorkingSet(WorkingSet<String> newSet) { // cancel any pending jobs so that we don't waste time loading images no longer needed loaderPool.clearJobs(); if (DEBUG) { System.out.println("RamTextureCache: changeWorkingSet:"); for (String imageId : newSet.getPrioritizedList()) System.out.printf("\t%s (pri %d)\n", imageId, newSet.getPriority(imageId)); } synchronized (cache) // because of race with imageLoaded() { // adjust priorities of already cached items. // (No longer needed items get super low priority) cache.updatePriority(newSet); // switch working sets curSet = newSet; // Start loading those which we are missing for (String imageId : newSet.getPrioritizedList()) { if (!cache.contains(imageId)) { if (DEBUG) System.out.printf("RamTextureCache: not cached: %s\n", imageId); loaderPool.addJob(imageId); } } } }
public void shutdown() { synchronized (cache) { cache.clear(); curSet.clear(); urgentImageIds.clear(); // wake any sleeping threads cache.notifyAll(); } loaderPool.shutdown(); }
public RamTextureCache(ResourceManager resMgr) { cache = new SizeBasedCache<String, GLImage>(256 * 1024 * 1024, this); cache.debugName = "RAM:SizeBasedCache"; loaderPool = new ImageLoaderPool(1, this, resMgr); curSet = new WorkingSet<String>(); urgentImageIds = new HashSet<String>(); }
/** * Get the GLImage associated with the specified image-id. If the image is cached in memory this * call will be very fast, otherwise it will be loaded from disk and saved to cache. * * @return null if the specified image is not in the current working set */ public GLImage getGLImage(String imageId) { synchronized (cache) { GLImage img = cache.get(imageId); if (img == null && curSet.contains(imageId)) { // elevate the urgency of this image if (DEBUG) System.out.printf("RamTextureCache: requesting immediate load of %s\n", imageId); urgentImageIds.add(imageId); loaderPool.makeTopPriority(imageId); long startTime = System.currentTimeMillis(); // wait for image to arrive while (curSet.contains(imageId) && !cache.contains(imageId)) { try { cache.wait(10000); img = cache.get(imageId); // timed out? if (img == null && (System.currentTimeMillis() - startTime) >= 10000) { System.err.println("RamTextureCache: timed out waiting for " + imageId); break; } } catch (InterruptedException e) { // ignore } } urgentImageIds.remove(imageId); // use fallback image if (img == null) img = GLImage.createNullImage(); } else if (DEBUG && img == null) System.out.printf("RamTextureCache: %s not in working set\n", imageId); return img; } }
public void imageLoaded(String filePath, GLImage image) { synchronized (cache) // because of race with changeWorkingSet() and getGLImage { int priority = curSet.getPriority(filePath); boolean isInCurSet = priority > Integer.MIN_VALUE; if (DEBUG) System.out.printf("RamTextureCache: loaded %s (pri=%d)\n", filePath, priority); // Store the loaded image in cache boolean full = !cache.store(filePath, image, image.nBytes, priority); // Stop loading images if the cache is full. // Second condition is important in case image was from previous // working set - we don't want to abort loading the new set if (full && isInCurSet) { if (DEBUG) System.out.println("RamTextureCache: cache is full, stop loading"); loaderPool.clearJobs(); } // wake up threads inside getGLImage() cache.notifyAll(); } }
public boolean shouldLoad(String filePath, int estimatedImageSize) { synchronized (cache) // because of race with changeWorkingSet() and getGLImage { // if somebody is waiting for it we have no choice if (urgentImageIds.contains(filePath) && curSet.contains(filePath)) return true; else { int priority = curSet.getPriority(filePath); // lower priority by one - ImageLoaderPool should not bother loading an image // if it's just going to replace one of equal priority - there's no point if (priority > Integer.MIN_VALUE) priority--; return cache.canStore(estimatedImageSize, priority); } } }