BuilderArena.allocate
This commit is contained in:
parent
0c56671f3c
commit
b63cfb11f1
6 changed files with 54 additions and 17 deletions
|
@ -2,7 +2,7 @@ package org.capnproto;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Vector;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public final class BuilderArena implements Arena {
|
public final class BuilderArena implements Arena {
|
||||||
|
|
||||||
|
@ -15,19 +15,18 @@ public final class BuilderArena implements Arena {
|
||||||
public static final AllocationStrategy SUGGESTED_ALLOCATION_STRATEGY =
|
public static final AllocationStrategy SUGGESTED_ALLOCATION_STRATEGY =
|
||||||
AllocationStrategy.GROW_HEURISTICALLY;
|
AllocationStrategy.GROW_HEURISTICALLY;
|
||||||
|
|
||||||
// Maybe this should be ArrayList?
|
public final ArrayList<SegmentBuilder> segments;
|
||||||
public final Vector<SegmentBuilder> segments;
|
|
||||||
|
|
||||||
public int nextSize;
|
public int nextSize;
|
||||||
public final AllocationStrategy allocationStrategy;
|
public final AllocationStrategy allocationStrategy;
|
||||||
|
|
||||||
|
|
||||||
public BuilderArena(int firstSegmentSizeWords, AllocationStrategy allocationStrategy) {
|
public BuilderArena(int firstSegmentSizeWords, AllocationStrategy allocationStrategy) {
|
||||||
this.segments = new Vector<SegmentBuilder>();
|
this.segments = new ArrayList<SegmentBuilder>();
|
||||||
this.nextSize = firstSegmentSizeWords;
|
this.nextSize = firstSegmentSizeWords;
|
||||||
this.allocationStrategy = allocationStrategy;
|
this.allocationStrategy = allocationStrategy;
|
||||||
SegmentBuilder segment0 = new SegmentBuilder(
|
SegmentBuilder segment0 = new SegmentBuilder(
|
||||||
ByteBuffer.allocate(firstSegmentSizeWords * Constants.BYTES_PER_WORD));
|
ByteBuffer.allocate(firstSegmentSizeWords * Constants.BYTES_PER_WORD), this);
|
||||||
segment0.buffer.mark();
|
segment0.buffer.mark();
|
||||||
segment0.buffer.order(ByteOrder.LITTLE_ENDIAN);
|
segment0.buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
this.segments.add(segment0);
|
this.segments.add(segment0);
|
||||||
|
@ -42,7 +41,10 @@ public final class BuilderArena implements Arena {
|
||||||
|
|
||||||
public static class AllocateResult {
|
public static class AllocateResult {
|
||||||
public final SegmentBuilder segment;
|
public final SegmentBuilder segment;
|
||||||
|
|
||||||
|
// offset to the beginning the of allocated memory
|
||||||
public final int offset;
|
public final int offset;
|
||||||
|
|
||||||
public AllocateResult(SegmentBuilder segment, int offset) {
|
public AllocateResult(SegmentBuilder segment, int offset) {
|
||||||
this.segment = segment;
|
this.segment = segment;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
|
@ -50,7 +52,23 @@ public final class BuilderArena implements Arena {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AllocateResult allocate(int amount) {
|
public AllocateResult allocate(int amount) {
|
||||||
throw new Error("unimplemented");
|
|
||||||
|
int len = this.segments.size();
|
||||||
|
// we allocate the first segment in the constructor.
|
||||||
|
|
||||||
|
int result = this.segments.get(len - 1).allocate(amount);
|
||||||
|
if (result != SegmentBuilder.FAILED_ALLOCATION) {
|
||||||
|
return new AllocateResult(this.segments.get(len - 1), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentBuilder newSegment = new SegmentBuilder(
|
||||||
|
ByteBuffer.allocate(amount * Constants.BYTES_PER_WORD),
|
||||||
|
this);
|
||||||
|
newSegment.buffer.mark();
|
||||||
|
newSegment.buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.segments.add(newSegment);
|
||||||
|
|
||||||
|
return new AllocateResult(newSegment, newSegment.allocate(amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ByteBuffer[] getSegmentsForOutput() {
|
public final ByteBuffer[] getSegmentsForOutput() {
|
||||||
|
|
|
@ -10,7 +10,7 @@ public final class MessageReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getRoot(FromStructReader<T> factory) {
|
public <T> T getRoot(FromStructReader<T> factory) {
|
||||||
SegmentReader segment = new SegmentReader(this.segmentSlices[0]);
|
SegmentReader segment = new SegmentReader(this.segmentSlices[0], new ReaderArena());
|
||||||
PointerReader pointerReader = PointerReader.getRoot(segment, 0,
|
PointerReader pointerReader = PointerReader.getRoot(segment, 0,
|
||||||
0x7fffffff /* XXX */);
|
0x7fffffff /* XXX */);
|
||||||
AnyPointer.Reader any = new AnyPointer.Reader(pointerReader);
|
AnyPointer.Reader any = new AnyPointer.Reader(pointerReader);
|
||||||
|
|
|
@ -3,12 +3,13 @@ package org.capnproto;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public final class SegmentBuilder extends SegmentReader {
|
public final class SegmentBuilder extends SegmentReader {
|
||||||
|
|
||||||
public static final int FAILED_ALLOCATION = -1;
|
public static final int FAILED_ALLOCATION = -1;
|
||||||
|
|
||||||
public int pos = 0; // in words
|
public int pos = 0; // in words
|
||||||
|
|
||||||
public SegmentBuilder(ByteBuffer buf) {
|
public SegmentBuilder(ByteBuffer buf, Arena arena) {
|
||||||
super(buf);
|
super(buf, arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the total number of words the buffer can hold
|
// the total number of words the buffer can hold
|
||||||
|
@ -22,10 +23,14 @@ public final class SegmentBuilder extends SegmentReader {
|
||||||
return this.pos;
|
return this.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
Allocate `amount` words.
|
Allocate `amount` words.
|
||||||
*/
|
*/
|
||||||
public final int allocate(int amount) {
|
public final int allocate(int amount) {
|
||||||
|
if (amount < 0) {
|
||||||
|
throw new InternalError("tried to allocate a negative number of words");
|
||||||
|
}
|
||||||
|
|
||||||
if (amount > this.capacity() - this.currentSize()) {
|
if (amount > this.capacity() - this.currentSize()) {
|
||||||
return FAILED_ALLOCATION; // no space left;
|
return FAILED_ALLOCATION; // no space left;
|
||||||
} else {
|
} else {
|
||||||
|
@ -34,4 +39,8 @@ public final class SegmentBuilder extends SegmentReader {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final BuilderArena getArena() {
|
||||||
|
return (BuilderArena)this.arena;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,10 @@ public class SegmentReader {
|
||||||
// invariant: buffer's mark is at its beginning.
|
// invariant: buffer's mark is at its beginning.
|
||||||
final ByteBuffer buffer;
|
final ByteBuffer buffer;
|
||||||
|
|
||||||
public SegmentReader(ByteBuffer buffer) {
|
final Arena arena;
|
||||||
|
|
||||||
|
public SegmentReader(ByteBuffer buffer, Arena arena) {
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
|
this.arena = arena;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,19 @@ final class WireHelpers {
|
||||||
|
|
||||||
// TODO check for nullness, amount == 0 case.
|
// TODO check for nullness, amount == 0 case.
|
||||||
|
|
||||||
int allocation = segment.allocate(amount);
|
int ptr = segment.allocate(amount);
|
||||||
if (allocation == SegmentBuilder.FAILED_ALLOCATION) {
|
if (ptr == SegmentBuilder.FAILED_ALLOCATION) {
|
||||||
//# Need to allocate in a new segment. We'll need to
|
//# Need to allocate in a new segment. We'll need to
|
||||||
//# allocate an extra pointer worth of space to act as
|
//# allocate an extra pointer worth of space to act as
|
||||||
//# the landing pad for a far pointer.
|
//# the landing pad for a far pointer.
|
||||||
|
|
||||||
|
int amountPlusRef = amount + Constants.POINTER_SIZE_IN_WORDS;
|
||||||
|
BuilderArena.AllocateResult allocation = segment.getArena().allocate(amountPlusRef);
|
||||||
|
|
||||||
throw new Error("unimplemented");
|
throw new Error("unimplemented");
|
||||||
} else {
|
} else {
|
||||||
WirePointer.setKindAndTarget(segment.buffer, refOffset, kind, allocation);
|
WirePointer.setKindAndTarget(segment.buffer, refOffset, kind, ptr);
|
||||||
return allocation;
|
return ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ class LayoutSuite extends FunSuite {
|
||||||
val buffer = java.nio.ByteBuffer.wrap(data);
|
val buffer = java.nio.ByteBuffer.wrap(data);
|
||||||
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
val pointerReader = new PointerReader(new SegmentReader(buffer), 0, 0x7fffffff);
|
val pointerReader = new PointerReader(new SegmentReader(buffer, new ReaderArena()), 0, 0x7fffffff);
|
||||||
val reader = pointerReader.getStruct();
|
val reader = pointerReader.getStruct();
|
||||||
|
|
||||||
assert(reader.getLongField(0) === 0xefcdab8967452301L);
|
assert(reader.getLongField(0) === 0xefcdab8967452301L);
|
||||||
|
@ -91,7 +91,10 @@ class LayoutSuite extends FunSuite {
|
||||||
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
||||||
buffer.mark();
|
buffer.mark();
|
||||||
|
|
||||||
val pointerBuilder = PointerBuilder.getRoot(new SegmentBuilder(buffer), 0);
|
val pointerBuilder = PointerBuilder.getRoot(
|
||||||
|
new SegmentBuilder(buffer, new BuilderArena(BuilderArena.SUGGESTED_FIRST_SEGMENT_WORDS,
|
||||||
|
BuilderArena.SUGGESTED_ALLOCATION_STRATEGY)),
|
||||||
|
0);
|
||||||
val builder = pointerBuilder.initStruct(new StructSize(2, 4, FieldSize.INLINE_COMPOSITE));
|
val builder = pointerBuilder.initStruct(new StructSize(2, 4, FieldSize.INLINE_COMPOSITE));
|
||||||
setupStruct(builder);
|
setupStruct(builder);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue