public class StackedMemory extends ScopedMemory
StackedMemory
implements a scoped memory allocation area
and backing store management system. It is designed to allow for
safe, fragmentation-free management of scoped allocation with certain
strong guarantees provided by the virtual machine and runtime
libraries.
Each StackedMemory
instance represents a single object
allocation area and additional memory associated with it in the form
of a backing store. The backing store associated with a
StackedMemory
is a fixed-size memory area allocated at
or before instantiation of the StackedMemory
. The
object allocation area is taken from the associated backing store,
and the backing store may be further subdivided into additional
StackedMemory
allocation areas or backing stores by
instantiating additional StackedMemory
objects.
When a StackedMemory
is created with a backing store, the
backing store may be taken from a notional global backing store, in
which case it is effectively immortal, or it may be taken from the
enclosing StackedMemory
's backing store when the scope in
which it is created is also a StackedMemory
. In this
case it is returned to its enclosing scope's backing store when the
object is finalized. Implementations should return the
space occupied by backing stores taken from the global backing store
when their associated StackedMemory
object is finalized.
These backing store semantics divide instances of
StackedMemory
into two categories:
StackedMemory
with an object allocation area
created in a new backing store, allocated either from the
global store or from a parent StackedMemory
's
backing store, andStackedMemory
with an object allocation area
taken directly from a parent StackedMemory
's
backing store without creating a sub-store.StackedMemory
object: root. A root
StackedMemory
is a host StackedMemory
created with a backing store drawn directly from the global backing
store, created in an allocation context of some type other than
StackedMemory
.
Creation of a StackedMemory
shall fail with a
StaticOutOfMemoryError
when the current
Schedulable
is configured with a limit on
ScopedMemoryParameters.maxGlobalBackingStore
and creation of the
root StackedMemory
would exceed that limit.
Creation of a StackedMemory
is subject to additional
restrictions when the current Schedulable
is configured with an
explicit initial memory area of type StackedMemory
. In this
case, the following rules apply.
StackedMemory
will fail and
throw a StaticOutOfMemoryError
regardless of
the value of the Schedulable
's
ScopedMemoryParameters.maxGlobalBackingStore
.StackedMemory
from a current
allocation context that is not the Schedulable
's
explicit initial memory area or one of its descendants in the
scope stack will fail and throw StaticOutOfMemoryError
.ScopedMemoryParameters.maxInitialBackingStore
bytes may be allocated directly from the backing store of the
Schedulable
's explicit initial memory area over the
lifetime of the Schedulable
. Any operation that would
exceed this limit (whether by resizing the allocation area of
the explicit initial memory area or a guest area in the same
backing store, or by allocating a new StackedMemory
with the explicit initial memory area as the current allocation
context) will fail and throw a StaticOutOfMemoryError
.
Allocations from a StackedMemory
object allocation area
are guaranteed to run in time linear in the size of the allocation.
All memory for the backing store must be reserved at object
construction time.
StackedMemory
memory areas have two additional
stacking constraints in addition to the single parent rule, designed
to enable fragmentation-free manipulation:
StackedMemory
that is created when another
StackedMemory
is the current allocation context
can only be entered from the same allocation context in which
it was created, and StackedMemory
may not be created from
a StackedMemory
that currently has another child
area that is also a guest StackedMemory
, i.e.,
a StackedMemory
can have at most one
direct child that is a guest StackedMemory
.
The StackedMemory
constructor semantics also enforce the
property that a StackedMemory
may not be created from
another StackedMemory
allocation context unless it is
allocated from that context's backing store as either a host or guest
area.
The backing store of a StackedMemory
behaves as if any
StackedMemory
object allocation areas are at the
“bottom” of the backing store, while the backing stores
for enclosed StackedMemory
areas are taken from the
“top” of the backing store.
There may be an implementation-specific memory overhead for creating
a backing store of a given size. This means that creating a
StackedMemory
with a backing store of exactly the
remaining available backing store of the current
StackedMemory
may fail with an
javax.realtime.StaticOutOfMemoryError
. This overhead must be
bounded by a constant.
Constructor and Description |
---|
StackedMemory(long scopeSize)
Equivalent to
StackedMemory(long, Runnable) with argument
list (scopeSize, null) . |
StackedMemory(long scopeSize,
long backingSize)
Equivalent to
StackedMemory(long, long, Runnable) with argument
list (scopeSize, backingSize, null) . |
StackedMemory(long scopeSize,
long backingSize,
java.lang.Runnable logic)
Creates a host
StackedMemory with an object
allocation area and backing store of the specified sizes, bound to
the specified Runnable . |
StackedMemory(long scopeSize,
java.lang.Runnable logic)
Create a guest
StackedMemory with an object
allocation area of the specified size, bound to the specified
Runnable . |
StackedMemory(SizeEstimator scopeSize)
Equivalent to
StackedMemory(long, Runnable) with argument
list (scopeSize.getEstimate(), null) . |
StackedMemory(SizeEstimator scopeSize,
java.lang.Runnable logic)
Equivalent to
StackedMemory(long, Runnable) with argument
list (scopeSize.getEstimate(), runnable) . |
StackedMemory(SizeEstimator scopeSize,
SizeEstimator backingSize)
Equivalent to
StackedMemory(long, long, Runnable) with argument
list (scopeSize.getEstimate(), backingSize.getEstimate(), null) . |
StackedMemory(SizeEstimator scopeSize,
SizeEstimator backingSize,
java.lang.Runnable logic)
Equivalent to
StackedMemory(long, long, Runnable) with argument
list (scopeSize.getEstimate(), backingSize.getEstimate(), runnable) . |
Modifier and Type | Method and Description |
---|---|
void |
enter()
Associates this memory area with the current
Schedulable object for the duration of the
run() method of the instance of
Runnable given in this object's constructor. |
void |
enter(java.lang.Runnable logic)
Associates this memory area with the current
Schedulable object for the duration of the
run() method of the given Runnable . |
long |
getMaximumSize()
Gets the maximum size this memory area can attain.
|
long |
hostBackingStoreConsumed()
Determines the amount of memory consumed by exisiting stacked memories
from the backing store of this stacked memory.
|
long |
hostBackingStoreRemaining()
Determines the amount of memory remaining for allocation to new
stacked memories in the backing store of this stacked memory.
|
long |
hostBackingStoreSize()
Determines the total amount of memory in the backing store of this
stacked memory.
|
void |
joinAndEnter()
In the error-free case,
joinAndEnter combines
join();enter(); such that no enter() from
another schedulable can intervene between the two method
invocations. |
void |
joinAndEnter(HighResolutionTime<?> time)
In the error-free case,
joinAndEnter combines
join();enter(); such that no enter() from
another schedulable can intervene between the two method
invocations. |
void |
joinAndEnter(java.lang.Runnable logic)
In the error-free case,
joinAndEnter combines
join(); and enter(); such that no enter()
from another schedulable can intervene between the two method
invocations. |
void |
joinAndEnter(java.lang.Runnable logic,
HighResolutionTime<?> time)
In the error-free case,
joinAndEnter combines
join();enter(); such that no enter() from
another schedulable can intervene between the two method
invocations. |
void |
resize(long scopeSize)
Changes the size of the object allocation area for this scope.
|
enter, enter, enter, enter, enter, executeInArea, executeInArea, executeInArea, executeInArea, executeInArea, executeInArea, finalize, getParent, getPortal, getReferenceCount, globalBackingStoreConsumed, globalBackingStoreRemaining, globalBackingStoreSize, join, join, joinAndEnter, joinAndEnter, joinAndEnter, joinAndEnter, joinAndEnter, joinAndEnter, joinAndEnter, joinAndEnter, joinAndEnter, joinAndEnter, newArray, newInstance, newInstance, setPortal, toString, visitNestedScopes, visitScopeRoots
getMemoryArea, mayHoldReferenceTo, mayHoldReferenceTo, memoryConsumed, memoryRemaining, newArrayInArea, size
public StackedMemory(long scopeSize, long backingSize, java.lang.Runnable logic)
StackedMemory
with an object
allocation area and backing store of the specified sizes, bound to
the specified Runnable
. The backing store is
allocated from the currently active memory area when it is also a
StackedMemory
, and the global backing store otherwise.
The object allocation area is allocated from the backing store.scopeSize
- Size of the allocation area within the backing store.backingSize
- Size of the total backing store.logic
- Runnable
to be entered using this
as its
current memory area when enter()
is called.StaticIllegalArgumentException
- when either
scopeSize
or backingSize
is less than zero,
or when scopeSize
is too large to be allocated from
a backing store of size backingSize
.StaticOutOfMemoryError
- when there is insufficient
memory available to reserve the requested backing store.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public StackedMemory(SizeEstimator scopeSize, SizeEstimator backingSize, java.lang.Runnable logic)
StackedMemory(long, long, Runnable)
with argument
list (scopeSize.getEstimate(), backingSize.getEstimate(), runnable)
.scopeSize
- SizeEstimator
indicating the size of the object
allocation area within the backing store.backingSize
- SizeEstimator
indicating the size of the total
backing store.logic
- Runnable
to be entered using this
as its
current memory area when enter()
is called.StaticIllegalArgumentException
- when either
scopeSize
or backingSize
is null
,
or when scopeSize.getEstimate()
is too large to be
allocated from a backing store of size
backingSize.getEstimate()
.StaticOutOfMemoryError
- when there is insufficient
memory available to reserve the requested backing store.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public StackedMemory(long scopeSize, long backingSize)
StackedMemory(long, long, Runnable)
with argument
list (scopeSize, backingSize, null)
.scopeSize
- Size of the allocation area within the backing store.backingSize
- Size of the total backing store.StaticIllegalArgumentException
- when either
scopeSize
or backingSize
is less than zero,
or when scopeSize
is too large to be allocated from
a backing store of size backingSize
.StaticOutOfMemoryError
- when there is insufficient
memory available to reserve the requested backing store.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public StackedMemory(SizeEstimator scopeSize, SizeEstimator backingSize)
StackedMemory(long, long, Runnable)
with argument
list (scopeSize.getEstimate(), backingSize.getEstimate(), null)
.scopeSize
- SizeEstimator
indicating the size of the object
allocation area within the backing store.backingSize
- SizeEstimator
indicating the size of the total
backing store.StaticIllegalArgumentException
- when either
scopeSize
or backingSize
is null
,
or when scopeSize.getEstimate()
is too large to be
allocated from a backing store of size
backingSize.getEstimate()
.StaticOutOfMemoryError
- when there is insufficient
memory available to reserve the requested backing store.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public StackedMemory(long scopeSize, java.lang.Runnable logic)
StackedMemory
with an object
allocation area of the specified size, bound to the specified
Runnable
. The object allocation area is drawn
from the same backing store as the parent scope's object allocation
area. The parent scope must be a StackedMemory
.scopeSize
- Size of the allocation area within the backing store.logic
- Runnable
to be entered using this
as its
current memory area when enter()
is called.StaticIllegalArgumentException
- when the
parent memory area is not a StackedMemory
.MemoryInUseException
- when the parent
StackedMemory
already has a child that is
also a guest StackedMemory
.StaticIllegalArgumentException
- when
scopeSize
is less than zero.StaticOutOfMemoryError
- when there is insufficient
memory available in the backing store of the parent
StackedMemory
's object allocation area to reserve
the requested object allocation area.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public StackedMemory(SizeEstimator scopeSize, java.lang.Runnable logic)
StackedMemory(long, Runnable)
with argument
list (scopeSize.getEstimate(), runnable)
.scopeSize
- SizeEstimator
indicating the size of
the object allocation area within the backing store.logic
- Runnable
to be entered using
this
as its current memory area when
enter()
is called.StaticIllegalArgumentException
- when the
parent memory area is not a StackedMemory
.MemoryInUseException
- when the parent
StackedMemory
already has a child that is
also a guest StackedMemory
.StaticIllegalArgumentException
- when
scopeSize
is null
.StaticOutOfMemoryError
- when there is
insufficient memory available in the backing store of the
parent StackedMemory
's object allocation area to
reserve the requested object allocation area.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public StackedMemory(long scopeSize)
StackedMemory(long, Runnable)
with argument
list (scopeSize, null)
.scopeSize
- Size of the allocation area within the backing store.StaticIllegalArgumentException
- when the
parent memory area is not a StackedMemory
.MemoryInUseException
- when the parent
StackedMemory
already has a child that is
also a guest StackedMemory
.StaticIllegalArgumentException
- when
scopeSize
is less than zero.StaticOutOfMemoryError
- when there is
insufficient memory available in the backing store of the
parent StackedMemory
's object allocation area to
reserve the requested object allocation area.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public StackedMemory(SizeEstimator scopeSize)
StackedMemory(long, Runnable)
with argument
list (scopeSize.getEstimate(), null)
.scopeSize
- SizeEstimator
indicating the size of the
object allocation area within the backing store.StaticIllegalArgumentException
- when the
parent memory area is not a StackedMemory
.MemoryInUseException
- when the parent
StackedMemory
already has a child that is
also a guest StackedMemory
.StaticIllegalArgumentException
- when
scopeSize
is null
.StaticOutOfMemoryError
- when there is
insufficient memory available in the backing store of the
parent StackedMemory
's object allocation area to
reserve the requested object allocation area.IllegalTaskStateException
- when the current
Schedulable
has a StackedMemory
as its explicit
initial scoped memory area and that area is not on the scope stack.public void resize(long scopeSize)
Schedulable
object has this area as its current allocation
context. It may be used to grow the allocation area, or to shrink
the allocation area no smaller than the size of its current usage,
when the calling Schedulable
object is the only object that
has this area on its scope stack and there are no guest
StackedMemory
object allocation areas created after this
area in the same backing store but not yet finalized.scopeSize
- The new allocation area size for this scope.StaticSecurityException
- when the caller is
not permitted to perform the requested adjustment.StaticIllegalArgumentException
- there
are additional guest StackedMemory
allocation areas after this one in the backing store.StaticOutOfMemoryError
- when the remaining
backing store is insufficient for the requested adjustment,
or when the current Schedulable
has a StackedMemory
as its explicit initial scoped memory area
and that area is not on the scope stack.public long getMaximumSize()
resize(long)
without triggering an
StaticOutOfMemoryError
.public long hostBackingStoreSize()
public long hostBackingStoreRemaining()
public long hostBackingStoreConsumed()
public void enter()
Schedulable
object for the duration of the
run()
method of the instance of
Runnable
given in this object's constructor. During
this period of execution, this memory area becomes the default
allocation context until another default allocation context is
selected.
This method may only be called from the memory area in which this scope was created.
enter
in class ScopedMemory
StaticIllegalArgumentException
- when the currently
active memory area is a StackedMemory
and is not the
area in which this scope was created, or the current memory
area is not a StackedMemory
and this
StackedMemory
is not a root area.ThrowBoundaryError
- Thrown when the JVM needs
to propagate an exception allocated in this
scope
to (or through) the memory area of the caller. Storing a
reference to that exception would cause an
IllegalAssignmentError
, so the JVM cannot
be permitted to deliver the exception. The
ThrowBoundaryError
is allocated in the
current allocation context and contains information about
the exception it replaces.IllegalTaskStateException
- when the execution context
is not an instance of Schedulable
or
when this method is invoked during finalization of objects in
scoped memory and entering this scoped memory area would force
deletion of the execution context that triggered
finalization. This would include the scope containing the
execution context, and the scope (if any) containing the
scope containing execution context.MemoryAccessError
- when caller is a schedulable that may not use the heap and
this memory area's logic value is allocated in heap memory.ScopedMemory.enter()
public void enter(java.lang.Runnable logic)
Schedulable
object for the duration of the
run()
method of the given Runnable
.
During this period of execution, this memory area becomes the
default allocation context until another default allocation
context is selected.
This method may only be called from the memory area in which this scope was created.
enter
in class ScopedMemory
logic
- The Runnable object whose run()
method should be invoked.StaticIllegalArgumentException
- when the currently
active memory area is a StackedMemory
and is not the
area in which this scope was created, or the current memory
area is not a StackedMemory
and this
StackedMemory
is not a root area.ThrowBoundaryError
- when the JVM needs
to propagate
an exception allocated in this
scope to (or
through) the memory area of the caller. Storing a
reference to that exception would cause an
IllegalAssignmentError
, so the JVM
cannot be permitted to deliver the exception. The
ThrowBoundaryError
is allocated in the
current allocation context and contains information about the
exception it replaces.IllegalTaskStateException
- when the execution context
is not an instance of Schedulable
or
when this method is invoked during finalization of objects in
scoped memory and entering this scoped memory area would force
deletion of the task that triggered finalization. This
would include the scope containing the task, and the scope
(if any) containing the scope containing task.MemoryAccessError
ScopedMemory.enter(Runnable)
public void joinAndEnter() throws java.lang.InterruptedException
ScopedMemory
joinAndEnter
combines
join();enter();
such that no enter()
from
another schedulable can intervene between the two method
invocations. The resulting method will wait for the reference
count on this ScopedMemory
to reach zero, then enters
the ScopedMemory
and executes the run
method from logic
passed in the constructor. When no
instance of Runnable
was passed to the memory area's
constructor, the method throws
StaticIllegalArgumentException
immediately.
When multiple threads are waiting in joinAndEnter
family methods for a memory area, at most one of them will
be released each time the reference count goes to zero.
Note that although joinAndEnter
guarantees that
the reference count is zero when the schedulable is released
for entry, it does not guarantee that the reference count will
remain one for any length of time. A subsequent enter
could raise the reference count to two.
joinAndEnter
in class ScopedMemory
java.lang.InterruptedException
- when this schedulable is interrupted by
RealtimeThread.interrupt()
or
AsynchronouslyInterruptedException.fire()
while waiting for the reference count to go to zero.public void joinAndEnter(HighResolutionTime<?> time) throws java.lang.InterruptedException
ScopedMemory
joinAndEnter
combines
join();enter();
such that no enter()
from
another schedulable can intervene between the two method
invocations. The resulting method will wait for the reference count
on this ScopedMemory
to reach zero, or for the current
time to reach the designated time, then enter the
ScopedMemory
and execute the run
method
from Runnable
object passed to the constructor. When no
instance of Runnable
was passed to the memory area's
constructor, the method throws
StaticIllegalArgumentException
immediately.
When multiple threads are waiting in joinAndEnter
family methods for a memory area, at most one of them will
be released each time the reference count goes to zero.
Since the time is expressed as a HighResolutionTime
,
this method has an accurate timer with nanosecond granularity. The
actual resolution of the timer and even the quantity it measures
depends on the clock associated with time
. The delay
time may be relative or absolute. When relative, then the calling
thread is blocked for at most the amount of time given by
time
, and measured by its associated clock. When
absolute, then the time delay is until the indicated value is
reached by the clock. When the given absolute time is less than or
equal to the current value of the clock, the call to
joinAndEnter
behaves effectively like ScopedMemory.enter()
.
Note that expiration of time
may cause control to
enter the memory area before its reference count has gone to zero.
joinAndEnter
in class ScopedMemory
time
- The time that bounds the wait.java.lang.InterruptedException
- when this schedulable is interrupted by
RealtimeThread.interrupt()
or
AsynchronouslyInterruptedException.fire()
while waiting for the reference count to go to zero.public void joinAndEnter(java.lang.Runnable logic) throws java.lang.InterruptedException
ScopedMemory
joinAndEnter
combines
join();
and enter();
such that no enter()
from another schedulable can intervene between the two method
invocations. The resulting method will wait for the reference count
on this ScopedMemory
to reach zero,
then enter the ScopedMemory
and execute the run
method from logic
When logic
is null
, the method throws
StaticIllegalArgumentException
immediately.
When multiple threads are waiting in joinAndEnter
family methods for a memory area, at most one of them will
be released each time the reference count goes to zero.
Note that although joinAndEnter
guarantees that
the reference count is zero when the schedulable is released
for entry, it does not guarantee that the reference count will
remain one for any length of time. A subsequent enter
could raise the reference count to two.
joinAndEnter
in class ScopedMemory
logic
- The Runnable
object which contains the
code to execute.java.lang.InterruptedException
- when this schedulable is interrupted by
RealtimeThread.interrupt()
or
AsynchronouslyInterruptedException.fire()
while waiting for the reference count to go to zero.public void joinAndEnter(java.lang.Runnable logic, HighResolutionTime<?> time) throws java.lang.InterruptedException
ScopedMemory
joinAndEnter
combines
join();enter();
such that no enter()
from
another schedulable can intervene between the two method
invocations. The resulting method will wait for the reference count
on this ScopedMemory
to reach zero, or for the current
time to reach the designated time, then enter the
ScopedMemory
and execute the run
method
from logic
.
Since the time is expressed as a HighResolutionTime
,
this method is an accurate timer with nanosecond granularity. The
actual resolution of the timer and even the quantity it measures
depends on the clock associated with time
. The delay
time may be relative or absolute. When relative, then the delay is
the amount of time given by time
, and measured by its
associated clock. When absolute, then the delay is until the
indicated value is reached by the clock. When the given absolute time
is less than or equal to the current value of the clock, the call
to joinAndEnter
behaves effectively like ScopedMemory.enter(Runnable)
.
The method throws StaticIllegalArgumentException
immediately when
logic
is null
.
When multiple threads are waiting in joinAndEnter
family methods for a memory area, at most one of them will
be released each time the reference count goes to zero.
Note that expiration of time
may cause control to
enter the memory area before its reference count has gone to zero.
joinAndEnter
in class ScopedMemory
logic
- The Runnable
object which contains the
code to execute.time
- The time that bounds the wait.java.lang.InterruptedException
- when this schedulable is interrupted by
RealtimeThread.interrupt()
or
AsynchronouslyInterruptedException.fire()
while waiting for the reference count to go to zero.