JSR-282 SI 25.3 Pinnable Memory ------------------------------------------------ Last Updated: 18 October 2006 ----------------------------- Address issues from discussions. Added two new methods and change one exception. Updated mail history. Version 4 --------- Summary --------------------- Add the capability to pass the content of a scoped memory between threads without an explicit handoff or extra wedge thread. Specification References --------------------- This SI proposes adding a new interface and subclasses of LTMemory, VTMemory, LTPhysicalMemory, and VTPhysicalMemory. Problem being Addressed --------------------- The current specification does not permit the contents of a scoped memory to be maintained when no thread is contained in a scope. Proposed Solution Summary --------------------- In package javax.realtime, add three interfaces and four new classes. public interface MemoryRegion { public void enter(); public void enter(Runnable logic); public void executeInArea(Runnable logic); public static MemoryArea getMemoryArea(Object object); public long memoryConsumed(); public long memoryRemaining(); public Object newArray(Class type, int number); public Object newInstance(Class type); public Object newInstance(Constructor c, Object[] args); public long size(); } where public class MemoryArea implements MemoryRegion; public interface ScopedRegion extends MemoryRegion { public void enter() throws ScopedCycleException; public void enter(Runnable logic) throws ScopedCycleException; public long getMaximumSize(); public Object getPortal() throws IllegalAssignmentError; public void setPortal(Object object); public int getReferenceCount(); public void join(HighResolutionTime time) throws InterruptedException; public void join() throws InterruptedException; public void joinAndEnter() throws InterruptedException; public void joinAndEnter(HighResolutionTime time) throws InterruptedException; public void joinAndEnter(Runnable logic) throws InterruptedException; public void joinAndEnter(Runnable logic, HighResolutionTime time) throws InterruptedException; public ScopedRegion getParent(); public void resize(long size) throws MemoryInUseException; } where public class ScopedMemory implements ScopedRegion; public interface PinnableRegion extends ScopedRegion { public void pin() throws IllegalStateException; public void unpin() throws IllegalStateException; } public class LTPinnableMemory extends LTMemory implements PinnableRegion; public class VTPinnableMemory extends VTMemory implements PinnableRegion; public class LTPinnablePhysicalMemory extends LTPhysicalMemory implements PinnableRegion; public class VTPinnablePhysicalMemory extends VTPhysicalMemory implements PinnableRegion; where pin and unpin are implemented and have all constructors as in the parent exception those that takes runables. Two new methods has been added to ScopedRegion and by implication to the underlying ScopedMemory class. The first method is getParent, which returns either null when the Region is not in used (not entered or pinned), itself when the region is the first region in a stack of scopes, or the parent ScopedRegion. The second method enables the size of an unoccupied (not entered and not pinned) ScopedRegion to be changed. It may also be set to zero to release the backing store. If the region is in use when resize is call, a MemoryInUseException is thrown. Semantics --------------------- The classes implementing PinnableRegion implement two new methods: pin and unpin. Calling pin prevents the scope from being freed when the reference count goes to zero until unpin is called. When unpin is call, the scope is freed once the reference count goes to zero. Both pin and unpin may only be called from within their respective scopes; otherwise an InaccessibleAreaException is thrown. Pinned scopes are allowed to be collected under some circumstances to minimize the danger of memory leaks to to lost pinned regions. Pinning a scope does not hold the parent alive. If the parent of a pinned scope is exited, the pinned scope is exited as well. Finalization is done by the parent thread. If a pinned scope object becomes unreachable, then the pinned scope is also unpinned. Since this is a programming error, no finalization is done. The finalizer of the PinnedScope object can be overridden to cause finalization by entering the scope and unpinning it explicitly when required. The choice of how finalization is done for pinned scopes is based on two principles: non pinned scopes should behave exactly like all other scoped memory areas and asynchronous finalization should be avoided. The programmer can guarentee finalization by always entering a pinned scope from some other scoped memory area. Always alocating pinned scoped objects in an scoped memory area will also reduce the scope of error. It may make sense to require this, e.g., throw an exception from the constructor when the current area is not a scoped memory area. Discussion Points --------------------- There are two alternate implementations options: 1) add the pin and unpin methods directly to ScopedMemory, or 2) have only a single fat interface for PinnableRegion. The first option make it difficult for programmers to indicate intent. Using a pinnable memory is a different pattern than using normal scoped memory. It is good to be able to recoginize this intent in the code. The second option would require PinnableRegion to declare all the methods of ScopeMemory and MemoryArea. A further option is to make pin and unpin counting. This does not seem to makes sense, since one can not guarentee that the number of producers and consumers would match for any given PinnableMemory. Some sort of registration process would be needed in any case to ensure that a scope gets unpinned at the correct time. Of course, the interface could be broken into three pieces: Memory, Scope, and PinnableMemory, where MemoryArea implements Memory, ScopedMemory implements Scope, the various pinnable memories implement PinnableMemory, Scope extends Memory, and PinnableMemory extends Scope. InaccessibleAreaException does not seem to be correct. MemoryAccessException would be better but there is only a MemoryAccessError. Compatibility Issues --------------------- None