Skip to content

Commit 8cbb524

Browse files
author
Jasper Geurtz
committed
wrappedbuffer
1 parent 7ec37f3 commit 8cbb524

File tree

2 files changed

+207
-15
lines changed

2 files changed

+207
-15
lines changed

src/main/java/bwapi/WrappedBuffer.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
* Wrapper around offheap memory that uses sun.misc.Unsafe for fast access.
1010
*/
1111
class WrappedBuffer {
12-
private final ByteBuffer buffer;
13-
private final long address;
12+
protected static final Unsafe UNSAFE = UnsafeTools.getUnsafe();
1413

15-
private static final Unsafe unsafe = UnsafeTools.getUnsafe();
14+
protected final ByteBuffer buffer;
15+
protected final long address;
1616

1717
WrappedBuffer(final int size) {
1818
buffer = ByteBuffer.allocateDirect(size);
@@ -25,42 +25,42 @@ class WrappedBuffer {
2525
}
2626

2727
byte getByte(final int offset) {
28-
return unsafe.getByte(address + offset);
28+
return UNSAFE.getByte(address + offset);
2929
}
3030

3131
void putByte(final int offset, final byte value) {
32-
unsafe.putByte(address + offset, value);
32+
UNSAFE.putByte(address + offset, value);
3333
}
3434

3535
short getShort(final int offset) {
36-
return unsafe.getShort(address + offset);
36+
return UNSAFE.getShort(address + offset);
3737
}
3838

3939
void putShort(final int offset, final short value) {
40-
unsafe.putShort(address + offset, value);
40+
UNSAFE.putShort(address + offset, value);
4141
}
4242

4343
int getInt(final int offset) {
44-
return unsafe.getInt(address + offset);
44+
return UNSAFE.getInt(address + offset);
4545
}
4646

4747
void putInt(final int offset, final int value) {
48-
unsafe.putInt(address + offset, value);
48+
UNSAFE.putInt(address + offset, value);
4949
}
5050

5151
double getDouble(final int offset) {
52-
return unsafe.getDouble(address + offset);
52+
return UNSAFE.getDouble(address + offset);
5353
}
5454

5555
void putDouble(final int offset, final double value) {
56-
unsafe.putDouble(address + offset, value);
56+
UNSAFE.putDouble(address + offset, value);
5757
}
5858

5959
String getString(final int offset, final int maxLen) {
6060
final char[] buf = new char[maxLen];
6161
long pos = offset + address;
6262
for (int i = 0; i < maxLen; i++) {
63-
byte b = unsafe.getByte(pos);
63+
byte b = UNSAFE.getByte(pos);
6464
if (b == 0) break;
6565
buf[i] = (char) (b & 0xff);
6666
pos++;
@@ -71,13 +71,12 @@ String getString(final int offset, final int maxLen) {
7171
void putString(final int offset, final int maxLen, final String string) {
7272
long pos = offset + address;
7373
for (int i = 0; i < Math.min(string.length(), maxLen - 1); i++) {
74-
unsafe.putByte(pos, (byte) string.charAt(i));
74+
UNSAFE.putByte(pos, (byte) string.charAt(i));
7575
pos++;
7676
}
77-
unsafe.putByte(pos, (byte) 0);
77+
UNSAFE.putByte(pos, (byte) 0);
7878
}
7979

80-
8180
ByteBuffer getBuffer() {
8281
return buffer;
8382
}
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package bwapi;
2+
3+
/**
4+
* Like WrappedBuffer but with offsets.
5+
*
6+
* <p> </p>For now this hardcodes a few things (size, offsets).
7+
*/
8+
class WrappedBufferOffset extends WrappedBuffer {
9+
// The "real" WrappedBuffer that contains the dynamic & static values.
10+
// WrappedBufferOffset makes a copy of the dynamic ones, but delegates
11+
// to the "real" one for the static values. This saves a lot of memory.
12+
private WrappedBuffer sourceBuffer;
13+
14+
WrappedBufferOffset() {
15+
super(DynamicData.SIZE);
16+
}
17+
18+
void setSourceBuffer(WrappedBuffer sourceBuffer) {
19+
if (sourceBuffer instanceof WrappedBufferOffset) {
20+
throw new RuntimeException("Only Non-Offset buffer can be sourceBuffer.");
21+
}
22+
this.sourceBuffer = sourceBuffer;
23+
}
24+
25+
void initialize() {
26+
// Copy the dynamic values from the underlying sourceBuffer.
27+
for (MemRegion region : DynamicData.MEM_REGIONS) {
28+
copyBuffer(region.start, region.offset, region.end - region.start);
29+
}
30+
}
31+
32+
byte getByte(final int offset) {
33+
int newOffset = DynamicData.offset(offset);
34+
if (newOffset == -1) {
35+
return sourceBuffer.getByte(offset);
36+
} else {
37+
return UNSAFE.getByte(address + newOffset);
38+
}
39+
}
40+
41+
void putByte(final int offset, final byte value) {
42+
int newOffset = DynamicData.offset(offset);
43+
if (newOffset == -1) {
44+
sourceBuffer.putByte(offset, value);
45+
} else {
46+
UNSAFE.putByte(address + newOffset, value);
47+
}
48+
}
49+
50+
short getShort(final int offset) {
51+
int newOffset = DynamicData.offset(offset);
52+
if (newOffset == -1) {
53+
return sourceBuffer.getShort(offset);
54+
} else {
55+
return UNSAFE.getShort(address + newOffset);
56+
}
57+
}
58+
59+
void putShort(final int offset, final short value) {
60+
int newOffset = DynamicData.offset(offset);
61+
if (newOffset == -1) {
62+
sourceBuffer.putShort(offset, value);
63+
} else {
64+
UNSAFE.putShort(address + newOffset, value);
65+
}
66+
}
67+
68+
int getInt(final int offset) {
69+
int newOffset = DynamicData.offset(offset);
70+
if (newOffset == -1) {
71+
return sourceBuffer.getInt(offset);
72+
} else {
73+
return UNSAFE.getInt(address + newOffset);
74+
}
75+
}
76+
77+
void putInt(final int offset, final int value) {
78+
int newOffset = DynamicData.offset(offset);
79+
if (newOffset == -1) {
80+
sourceBuffer.putInt(offset, value);
81+
} else {
82+
UNSAFE.putInt(address + newOffset, value);
83+
}
84+
}
85+
86+
double getDouble(final int offset) {
87+
int newOffset = DynamicData.offset(offset);
88+
if (newOffset == -1) {
89+
return sourceBuffer.getDouble(offset);
90+
} else {
91+
return UNSAFE.getDouble(address + newOffset);
92+
}
93+
}
94+
95+
void putDouble(final int offset, final double value) {
96+
int newOffset = DynamicData.offset(offset);
97+
if (newOffset == -1) {
98+
sourceBuffer.putDouble(offset, value);
99+
} else {
100+
UNSAFE.putDouble(address + newOffset, value);
101+
}
102+
}
103+
104+
String getString(final int offset, final int maxLen) {
105+
int newOffset = DynamicData.offset(offset);
106+
if (newOffset == -1) {
107+
return sourceBuffer.getString(offset, maxLen);
108+
}
109+
else {
110+
final char[] buf = new char[maxLen];
111+
long pos = newOffset + address;
112+
for (int i = 0; i < maxLen; i++) {
113+
byte b = UNSAFE.getByte(pos);
114+
if (b == 0) break;
115+
buf[i] = (char) (b & 0xff);
116+
pos++;
117+
}
118+
return new String(buf, 0, (int) (pos - newOffset - address));
119+
}
120+
}
121+
122+
void putString(final int offset, final int maxLen, final String string) {
123+
int newOffset = DynamicData.offset(offset);
124+
if (newOffset == -1) {
125+
sourceBuffer.putString(offset, maxLen, string);
126+
}
127+
else {
128+
long pos = newOffset + address;
129+
for (int i = 0; i < Math.min(string.length(), maxLen - 1); i++) {
130+
UNSAFE.putByte(pos, (byte) string.charAt(i));
131+
pos++;
132+
}
133+
UNSAFE.putByte(pos, (byte) 0);
134+
}
135+
}
136+
137+
private void copyBuffer(long sourceOffset, long destinationOffset, int size) {
138+
long addressSource = sourceBuffer.getAddress() + sourceOffset;
139+
long addressDestination = this.getAddress() + destinationOffset;
140+
UNSAFE.copyMemory(addressSource, addressDestination, size);
141+
}
142+
143+
144+
// These blocks account for *most* of the 33MB shared memory,
145+
// so omitting them drastically reduces the copy duration
146+
static final class DynamicData {
147+
// TODO: infer these from clientdata instead of hardcoding.
148+
149+
static final int OFFSET_0 = 0;
150+
static final int STATICTILES_START = 3447004; // getGroundHeight, isWalkable, isBuildable
151+
static final int OFFSET_1 = STATICTILES_START;
152+
153+
static final int STATICTILES_END = 4823260;
154+
static final int REGION_START = 5085404; // getMapTileRegionId, ..., getRegions
155+
static final int OFFSET_2 = OFFSET_1 + (REGION_START - STATICTILES_END);
156+
157+
static final int REGION_END = 10586480;
158+
static final int STRINGSSHAPES_START = 10962632; // getStringCount, ... getShapes
159+
static final int OFFSET_3 = OFFSET_2 + (STRINGSSHAPES_START - REGION_END);
160+
161+
static final int STRINGSHAPES_END = 32242636;
162+
static final int UNITFINDER_START = 32962644;
163+
static final int SIZE = OFFSET_3 + (UNITFINDER_START - STRINGSHAPES_END);
164+
165+
static int offset(int offset) {
166+
for (MemRegion r : MEM_REGIONS) {
167+
if (offset >= r.start && offset < r.end) {
168+
return offset - r.offset;
169+
}
170+
}
171+
return -1;
172+
}
173+
174+
static final MemRegion[] MEM_REGIONS = new MemRegion[]{
175+
new MemRegion(0, STATICTILES_START, OFFSET_0),
176+
new MemRegion(STATICTILES_END, REGION_START, OFFSET_1),
177+
new MemRegion(REGION_END, STRINGSSHAPES_START, OFFSET_2),
178+
new MemRegion(STRINGSHAPES_END, UNITFINDER_START, OFFSET_3)
179+
};
180+
}
181+
182+
private static class MemRegion {
183+
final int start;
184+
final int end;
185+
final int offset;
186+
187+
MemRegion(int start, int end, int offset) {
188+
this.start = start;
189+
this.end = end;
190+
this.offset = offset;
191+
}
192+
}
193+
}

0 commit comments

Comments
 (0)