public class Chunk extends Object
A chunk of binary data.
Each Chunk
holds a fixed-sized byte array
that may be used to store arbitrary binary data; offset
and length
properties are used to define the range
of significant data within the array.
Chunks are usually reused within the system; in such cases each
Chunk
corresponds to some pool
instance.
A chunk may be acquired from the specified pool by invocation of
getChunk(owner)
method and after being used
it may be returned back to the pool by recycle(owner)
method.
(The owner argument of these methods will be described below.)
It is is also possible to create a chunk without binding it with any pool,
simply by wrapping
a given byte array.
The concept of a chunk is concerned with the concept of a linear type. The main idea is that there may always exist at most one reference for every chunk within the system. Each time a reference to some chunk instance is passed from one part of the system to another (e.g. as some method argument or return value, by assignment to another variable or in any other way) it may no longer be used in its previous location.
In order to ensure that every chunk may be used from a single place at any
moment of time, the owner for every chunk is introduced.
Each chunk always corresponds to exactly one owner, representing the current
part of the system which this chunk currently belongs to.
A reference to any arbitrary object may be used as an owner for a chunk.
Each time a chunk is passed to another part of the system, its owner
is validated and changed to a new value.
This operation is called handover
.
Each handover or modification operation requires to be provided with
the reference to the current owner of the chunk, and it fails with
IllegalStateException
in case this reference is incorrect.
Thus, only the true owner of the chunk may modify it or hand it over
to someone else (and it may do this at most once).
Note, that getBytes()
method, however, does not validate
the owner, in spite of the fact that it may be used to modify the contents
of the chunk. Moreover, this method potentially allows to store the
reference for the underlying byte array of the chunk even after it was
recycled or handed over to someone else (which is strictly forbidden).
Therefore it must be used with great care (see method
documentation
for more details on its usage).
When a chunk is no longer needed and is not passed anywhere else,
it should be returned into its pool via recycle(owner)
method.
Recycling a chunk implies its handover from the current owner to the pool,
so a chunk may no longer be used after being recycled, as well as it
may not be recycled if is passed somewhere else (in the latter case
it is recipient's responsibility to recycle the chunk after it is
no longer needed).
In case it is required to pass the same chunk into several different places
or to store its underlying binary data somewhere for a long time without
knowing exactly whether it is still used or not,
markReadOnly(owner)
method may be used. This method marks
the chunk as read-only and since this moment it is excluded
from pooling turnover. In order to check whether a chunk is read-only
or not isReadOnly()
method can be used.
All read-only chunks are owned by special read-only owner, which
means that they are actually owned by everybody except for the fact that
no one may modify them.
Handing over
read-only chunk is, however,
still allowed: it just does not actually change the owner.
In particular, invocation of recycle(owner)
method would have
no effect on a read-only chunk.
All modifying methods (such as setLength(length, owner)
and
setRange(offset, length, owner)
) would throw an IllegalStateException
on a read-only chunk. The underlying byte array, however, may still be accessed and, thus, modified but this is
strictly forbidden by convention.
All chunks are modifiable (not read-only) by default. A chunk once marked as read-only can never become modifiable again. References to read-only chunks may be spawned and stored infinitely because they would never be modified or recycled and reused again by anyone.
handOver
method or
recycles it via recyle
method, so an original owner of the
chunk can no longer use it after invocation of such a method, unless the chunk is read-only, in which
case it can be still used (both methods do nothing when chunk is read-only).
The only only exception are read-only
chunks that can be used (for read only)
concurrently from multiple threads.
ChunkList
,
ChunkPool
,
ChunkedInput
,
ChunkedOutput
Modifier and Type | Field and Description |
---|---|
protected byte[] |
bytes |
protected int |
length |
protected int |
offset |
protected WeakReference<ChunkPool> |
poolReference |
Modifier | Constructor and Description |
---|---|
protected |
Chunk(ChunkPool pool,
byte[] bytes,
Object owner)
Constructs a new chunk of specified owner that wraps given byte array.
|
Modifier and Type | Method and Description |
---|---|
protected void |
checkOwner(Object owner)
Throws an exception if the chunk is not owned by specified owner.
|
byte[] |
getBytes()
Returns byte array, wrapped by this chunk.
|
int |
getLength()
Returns the total number of meaningful bytes stored in this chunk's
underlying byte array . |
int |
getOffset()
Returns the position of the first meaningful byte in this chunk's
underlying byte array . |
ChunkPool |
getPool()
Returns chunk pool that this chunk was allocated from or
null if none. |
void |
handOver(Object oldOwner,
Object newOwner)
Hands over the chunk to another owner.
|
boolean |
isReadOnly()
Checks whether the chunk is read-only.
|
void |
markReadOnly(Object owner)
Marks this chunk as
read-only . |
void |
recycle(Object owner)
Returns the chunk into the pool (or invalidates it if it does not correspond to any pool).
|
void |
setLength(int length,
Object owner)
Sets the total number of meaningful bytes stored in this chunk's
underlying byte array . |
void |
setRange(int offset,
int length,
Object owner)
Sets the range occupied by meaningful data within this chunk's
underlying byte array . |
String |
toString()
Returns a string representation of the object.
|
static Chunk |
wrap(byte[] bytes,
int offset,
int length,
Object owner)
Constructs a new chunk of specified owner that wraps given byte array with
specified range of data and does not correspond to any
pool . |
static Chunk |
wrap(byte[] bytes,
Object owner)
Constructs new chunk of specified owner that wraps given byte array
and does not correspond to any
pool . |
protected final WeakReference<ChunkPool> poolReference
protected final byte[] bytes
protected int offset
protected int length
protected Chunk(ChunkPool pool, byte[] bytes, Object owner)
pool
- pool that will be used to recycle this chunkbytes
- byte array that will be wrapped by this chunkowner
- owner of the new chunkNullPointerException
- if bytes
is null
public static Chunk wrap(byte[] bytes, Object owner)
pool
.
Note: wrapping must be used only with 'throw-away' arrays that will not be used by source code after wrapping.
bytes
- the byte array to wrapowner
- owner of the new chunkNullPointerException
- if bytes
is null
.public static Chunk wrap(byte[] bytes, int offset, int length, Object owner)
pool
.
Note: wrapping must be used only with 'throw-away' arrays that will not be used by source code after wrapping.
bytes
- the byte array to wrapoffset
- position of the first meaningful bytelength
- total number of meaningful bytesowner
- owner of the new chunkNullPointerException
- if bytes
is null
.IndexOutOfBoundsException
- if the region defined by
offset
and length
is out of underlying byte array rangepublic ChunkPool getPool()
null
if none.null
if none.public byte[] getBytes()
Note: although this method can access underlying bytes of a chunk
regardless of its owner and "read-only" status, it is strictly forbidden
to modify the bytes if the chunk is read-only
or
is owned by someone else.
It is neither allowed to recycle the chunk or hand it over to someone
else while you are using its underlying byte array.
A caution is required when passing this byte array into various
routines in order to be sure, that these routines won't store
a reference to the array to access it later.
public int getOffset()
underlying byte array
.underlying byte array
public int getLength()
underlying byte array
.underlying byte array
public void setLength(int length, Object owner)
underlying byte array
.length
- total number of meaningful bytes stored in this chunk's
underlying byte array
owner
- owner of the chunkIndexOutOfBoundsException
- if length
is negative or if
offset+length
exceeds underlying array lengthIllegalStateException
- if the chunk's owner differs from
the one specified (in particular, if the chunk is read-only).public void setRange(int offset, int length, Object owner)
underlying byte array
.offset
- position of the first meaningful bytelength
- total number of meaningful bytesowner
- owner of the chunkIndexOutOfBoundsException
- if the region defined by
offset
and length
is out of underlying
byte array rangeIllegalStateException
- if the chunk's owner differs from
the one specified (in particular, if the chunk is read-only).public boolean isReadOnly()
true
if this chunk is read-only.markReadOnly(Object)
public void markReadOnly(Object owner)
read-only
.
Does nothing if the chunk is already read-only.owner
- current owner of the chunkIllegalStateException
- if the chunk is not read-only
and its current owner differs from the one specifiedpublic void handOver(Object oldOwner, Object newOwner)
read-only
.oldOwner
- old (current) owner of the chunknewOwner
- new owner of the chunkIllegalStateException
- if the chunk is not read-only
and its current owner differs from the one specifiedpublic void recycle(Object owner)
read-only
.
A reference to this chunk is considered to become invalid after
invocation of this method and may no longer be used, unless the chunk was read-only.owner
- current owner of the chunkIllegalStateException
- if the chunk is not
read-only
and its current owner differs from the one specifiedprotected void checkOwner(Object owner)
owner
- expected owner of the chunkIllegalStateException
- if the chunk's current owner differs
from the one specifiedCopyright © 2002–2025 Devexperts LLC. All rights reserved.