package freenet.support; /** Represents a chunk of some limited resource, usually an estimate of bytes of memory in use, * which has been allocated to a MemoryLimitedJob. Can be released but not added to. * @author toad */ public final class MemoryLimitedChunk { private final MemoryLimitedJobRunner memoryLimitedJobRunner; private long used; MemoryLimitedChunk(MemoryLimitedJobRunner memoryLimitedJobRunner, long used) { this.memoryLimitedJobRunner = memoryLimitedJobRunner; if(used < 0) throw new IllegalArgumentException(); this.used = used; } /** Should be called when the caller has finished using the resource. Usually when a * MemoryLimitedJob has stopped using a large temporary buffer, and has made it GC'able, that * is, there are no more (non-weak) pointers to it. */ public long release() { long released = 0; synchronized(this) { if(used == 0) return 0; released = used; used = 0; } this.memoryLimitedJobRunner.deallocate(released, true); return released; } /** Should be called when the caller is now using a smaller amount of the resource, e.g. we * go from a big buffer to a small buffer. Note that this is irreversible. */ public long release(long amount) { boolean finishedThread = false; synchronized(this) { if(amount > used) throw new IllegalArgumentException("Only have "+used+" in use but asked to release "+amount); used -= amount; finishedThread = (used == 0); } this.memoryLimitedJobRunner.deallocate(amount, finishedThread); return amount; } MemoryLimitedJobRunner getRunner() { return this.memoryLimitedJobRunner; } }