Skip to content

Commit 1a03297

Browse files
committed
iter direct access field improvement
1 parent 881f191 commit 1a03297

2 files changed

Lines changed: 69 additions & 39 deletions

File tree

examples/src/main/java/com/github/elebras1/flecs/examples/DirectFieldAccessExample.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ public static void main(String[] args) {
4545
float y = iter.fieldFloat(Position.class, 0, "y", i);
4646
int health = iter.fieldInt(Health.class, 2, "value", i);
4747
System.out.printf(" pos=(%.1f, %.1f) health=%d%n", x, y, health);
48+
49+
iter.setFieldFloat(Position.class, 0, "x", i, x + 1.0f);
50+
iter.setFieldFloat(Position.class, 0, "y", i, y + 1.0f);
51+
iter.setFieldInt(Health.class, 2, "value", i, health - 1);
52+
53+
x = iter.fieldFloat(Position.class, 0, "x", i);
54+
y = iter.fieldFloat(Position.class, 0, "y", i);
55+
health = iter.fieldInt(Health.class, 2, "value", i);
56+
System.out.println(" After update: pos=(" + x + ", " + y + ") health=" + health);
4857
}
4958
});
5059
}

src/main/java/com/github/elebras1/flecs/Iter.java

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,31 @@
22

33
import java.lang.foreign.MemorySegment;
44
import java.lang.foreign.ValueLayout;
5+
import java.util.Arrays;
56

67
public class Iter {
7-
8+
89
private MemorySegment nativeIter;
910
private final World world;
1011
private int count;
12+
private final MemorySegment[] cachedColumns;
1113

1214
Iter(MemorySegment nativeIter, World world) {
1315
this.nativeIter = nativeIter;
1416
this.world = world;
1517
this.count = -1;
18+
this.cachedColumns = new MemorySegment[32];
1619
}
1720

1821
void setNativeIter(MemorySegment nativeIter) {
1922
this.nativeIter = nativeIter;
2023
this.count = -1;
24+
Arrays.fill(cachedColumns, null);
2125
}
2226

2327
public boolean next() {
2428
this.count = -1;
29+
Arrays.fill(cachedColumns, null);
2530
return flecs_h.ecs_iter_next(this.nativeIter);
2631
}
2732

@@ -37,6 +42,9 @@ public long entityId(int index) {
3742
throw new IndexOutOfBoundsException("Index " + index + " out of bounds for count " + this.count());
3843
}
3944
MemorySegment entities = ecs_iter_t.entities(this.nativeIter);
45+
if (entities == null || entities.address() == 0) {
46+
throw new IllegalStateException("Entities array is null");
47+
}
4048
return entities.getAtIndex(ValueLayout.JAVA_LONG, index);
4149
}
4250

@@ -107,97 +115,111 @@ public int fieldCount() {
107115
return Byte.toUnsignedInt(ecs_iter_t.field_count(this.nativeIter));
108116
}
109117

110-
private <T> MemorySegment fieldPtr(Class<T> componentClass, int index, String fieldName, int i, long[] outOffset) {
118+
private <T> long fieldPtr(Class<T> componentClass, int index, String fieldName, int i) {
111119
if (index < 0 || index > 127) {
112120
throw new IndexOutOfBoundsException("The field index must be between 0 and 127.");
113121
}
122+
if (i < 0 || i >= this.count()) {
123+
throw new IndexOutOfBoundsException("Entity index " + i + " out of bounds for count " + this.count());
124+
}
125+
114126
Component<T> component = this.world.componentRegistry().getComponent(componentClass);
115-
MemorySegment columnPtr = flecs_h.ecs_field_w_size(this.nativeIter, component.size(), (byte) index);
116-
outOffset[0] = i * component.size() + component.offsetOf(fieldName);
117-
return columnPtr;
127+
128+
MemorySegment columnPtr = this.cachedColumns[index];
129+
if (columnPtr == null) {
130+
columnPtr = flecs_h.ecs_field_w_size(this.nativeIter, component.size(), (byte) index);
131+
if (columnPtr == null || columnPtr.address() == 0) {
132+
throw new IllegalStateException("Field " + index + " is not available");
133+
}
134+
this.cachedColumns[index] = columnPtr;
135+
}
136+
137+
return i * component.size() + component.offsetOf(fieldName);
118138
}
119139

120140
public <T> int fieldInt(Class<T> componentClass, int index, String fieldName, int i) {
121-
long[] offset = new long[1];
122-
return this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.JAVA_INT, offset[0]);
141+
long offset = fieldPtr(componentClass, index, fieldName, i);
142+
return this.cachedColumns[index].get(ValueLayout.JAVA_INT, offset);
123143
}
124144

125145
public <T> float fieldFloat(Class<T> componentClass, int index, String fieldName, int i) {
126-
long[] offset = new long[1];
127-
return this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.JAVA_FLOAT, offset[0]);
146+
long offset = fieldPtr(componentClass, index, fieldName, i);
147+
return this.cachedColumns[index].get(ValueLayout.JAVA_FLOAT, offset);
128148
}
129149

130150
public <T> double fieldDouble(Class<T> componentClass, int index, String fieldName, int i) {
131-
long[] offset = new long[1];
132-
return this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.JAVA_DOUBLE, offset[0]);
151+
long offset = fieldPtr(componentClass, index, fieldName, i);
152+
return this.cachedColumns[index].get(ValueLayout.JAVA_DOUBLE, offset);
133153
}
134154

135155
public <T> long fieldLong(Class<T> componentClass, int index, String fieldName, int i) {
136-
long[] offset = new long[1];
137-
return this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.JAVA_LONG, offset[0]);
156+
long offset = fieldPtr(componentClass, index, fieldName, i);
157+
return this.cachedColumns[index].get(ValueLayout.JAVA_LONG, offset);
138158
}
139159

140160
public <T> short fieldShort(Class<T> componentClass, int index, String fieldName, int i) {
141-
long[] offset = new long[1];
142-
return this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.JAVA_SHORT, offset[0]);
161+
long offset = fieldPtr(componentClass, index, fieldName, i);
162+
return this.cachedColumns[index].get(ValueLayout.JAVA_SHORT, offset);
143163
}
144164

145165
public <T> boolean fieldBoolean(Class<T> componentClass, int index, String fieldName, int i) {
146-
long[] offset = new long[1];
147-
return this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.JAVA_BOOLEAN, offset[0]);
166+
long offset = fieldPtr(componentClass, index, fieldName, i);
167+
return this.cachedColumns[index].get(ValueLayout.JAVA_BOOLEAN, offset);
148168
}
149169

150170
public <T> byte fieldByte(Class<T> componentClass, int index, String fieldName, int i) {
151-
long[] offset = new long[1];
152-
return this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.JAVA_BYTE, offset[0]);
171+
long offset = fieldPtr(componentClass, index, fieldName, i);
172+
return this.cachedColumns[index].get(ValueLayout.JAVA_BYTE, offset);
153173
}
154174

155175
public <T> String fieldString(Class<T> componentClass, int index, String fieldName, int i) {
156-
long[] offset = new long[1];
157-
MemorySegment stringPointer = this.fieldPtr(componentClass, index, fieldName, i, offset).get(ValueLayout.ADDRESS.withByteAlignment(1), offset[0]);
176+
long offset = fieldPtr(componentClass, index, fieldName, i);
177+
MemorySegment stringPointer = this.cachedColumns[index].get(ValueLayout.ADDRESS.withByteAlignment(1), offset);
178+
158179
if (stringPointer.address() == 0) {
159180
return null;
160181
}
161-
return stringPointer.reinterpret(Long.MAX_VALUE).getString(0);
182+
183+
return stringPointer.reinterpret(Short.MAX_VALUE).getString(0);
162184
}
163185

164186
public <T> void setFieldInt(Class<T> componentClass, int index, String fieldName, int i, int value) {
165-
long[] offset = new long[1];
166-
this.fieldPtr(componentClass, index, fieldName, i, offset).set(ValueLayout.JAVA_INT, offset[0], value);
187+
long offset = fieldPtr(componentClass, index, fieldName, i);
188+
this.cachedColumns[index].set(ValueLayout.JAVA_INT, offset, value);
167189
}
168190

169191
public <T> void setFieldFloat(Class<T> componentClass, int index, String fieldName, int i, float value) {
170-
long[] offset = new long[1];
171-
this.fieldPtr(componentClass, index, fieldName, i, offset).set(ValueLayout.JAVA_FLOAT, offset[0], value);
192+
long offset = fieldPtr(componentClass, index, fieldName, i);
193+
this.cachedColumns[index].set(ValueLayout.JAVA_FLOAT, offset, value);
172194
}
173195

174196
public <T> void setFieldDouble(Class<T> componentClass, int index, String fieldName, int i, double value) {
175-
long[] offset = new long[1];
176-
this.fieldPtr(componentClass, index, fieldName, i, offset).set(ValueLayout.JAVA_DOUBLE, offset[0], value);
197+
long offset = fieldPtr(componentClass, index, fieldName, i);
198+
this.cachedColumns[index].set(ValueLayout.JAVA_DOUBLE, offset, value);
177199
}
178200

179201
public <T> void setFieldLong(Class<T> componentClass, int index, String fieldName, int i, long value) {
180-
long[] offset = new long[1];
181-
this.fieldPtr(componentClass, index, fieldName, i, offset).set(ValueLayout.JAVA_LONG, offset[0], value);
202+
long offset = fieldPtr(componentClass, index, fieldName, i);
203+
this.cachedColumns[index].set(ValueLayout.JAVA_LONG, offset, value);
182204
}
183205

184206
public <T> void setFieldShort(Class<T> componentClass, int index, String fieldName, int i, short value) {
185-
long[] offset = new long[1];
186-
this.fieldPtr(componentClass, index, fieldName, i, offset).set(ValueLayout.JAVA_SHORT, offset[0], value);
207+
long offset = fieldPtr(componentClass, index, fieldName, i);
208+
this.cachedColumns[index].set(ValueLayout.JAVA_SHORT, offset, value);
187209
}
188210

189211
public <T> void setFieldBoolean(Class<T> componentClass, int index, String fieldName, int i, boolean value) {
190-
long[] offset = new long[1];
191-
this.fieldPtr(componentClass, index, fieldName, i, offset).set(ValueLayout.JAVA_BOOLEAN, offset[0], value);
212+
long offset = fieldPtr(componentClass, index, fieldName, i);
213+
this.cachedColumns[index].set(ValueLayout.JAVA_BOOLEAN, offset, value);
192214
}
193215

194216
public <T> void setFieldByte(Class<T> componentClass, int index, String fieldName, int i, byte value) {
195-
long[] offset = new long[1];
196-
this.fieldPtr(componentClass, index, fieldName, i, offset).set(ValueLayout.JAVA_BYTE, offset[0], value);
217+
long offset = fieldPtr(componentClass, index, fieldName, i);
218+
this.cachedColumns[index].set(ValueLayout.JAVA_BYTE, offset, value);
197219
}
198220

199221
public <T> void setFieldString(Class<T> componentClass, int index, String fieldName, int i, String value) {
200-
// TODO
222+
throw new UnsupportedOperationException("setFieldString not yet implemented");
201223
}
202224

203225
public long event() {
@@ -211,5 +233,4 @@ public Table table() {
211233
}
212234
return new Table(this.world, tablePtr);
213235
}
214-
}
215-
236+
}

0 commit comments

Comments
 (0)