Skip to content

Commit 86de943

Browse files
committed
fix multithreading of system/observer callback + use valueLayout of java
1 parent 0a36221 commit 86de943

4 files changed

Lines changed: 30 additions & 27 deletions

File tree

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static void main(String[] args) {
4646
.with(posId)
4747
.rate(2)
4848
.kind(FlecsConstants.EcsOnUpdate)
49-
.run(it -> {
49+
.iter(it -> {
5050
System.out.println(" [Rate Filter] Running every 2nd frame (matched: " + it.count() + " entities)");
5151
});
5252

@@ -69,12 +69,13 @@ public static void main(String[] args) {
6969
for (int i = 0; i < it.count(); i++) {
7070
Position pos = positions.get(i);
7171
Velocity vel = velocities.get(i);
72-
72+
7373
float newX = pos.x() + vel.dx() * it.deltaTime();
7474
float newY = pos.y() + vel.dy() * it.deltaTime();
7575
long entityId = it.entity(i);
7676
Entity entity = world.obtainEntity(entityId);
7777
entity.set(new Position(newX, newY));
78+
// Note: System.out.printf removed to avoid synchronization issues with multi-threading
7879
}
7980
});
8081

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.elebras1.flecs;
22

33
import java.lang.foreign.MemorySegment;
4+
import java.lang.foreign.ValueLayout;
45

56
public class Iter {
67

@@ -36,7 +37,7 @@ public long entityId(int index) {
3637
throw new IndexOutOfBoundsException("Index " + index + " out of bounds for count " + this.count());
3738
}
3839
MemorySegment entities = ecs_iter_t.entities(this.nativeIter);
39-
return entities.getAtIndex(flecs_h$shared.C_LONG, index);
40+
return entities.getAtIndex(ValueLayout.JAVA_LONG, index);
4041
}
4142

4243
public long entity(int index) {
@@ -86,7 +87,7 @@ public long termId(int index) {
8687
return 0;
8788
}
8889

89-
return ids.getAtIndex(flecs_h$shared.C_LONG, index);
90+
return ids.getAtIndex(ValueLayout.JAVA_LONG, index);
9091
}
9192

9293
public int fieldSize(int index) {
@@ -99,7 +100,7 @@ public int fieldSize(int index) {
99100
return 0;
100101
}
101102

102-
return sizes.getAtIndex(flecs_h$shared.C_INT, index);
103+
return sizes.getAtIndex(ValueLayout.JAVA_INT, index);
103104
}
104105

105106
public int fieldCount() {

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,16 @@ public ObserverBuilder observerFlags(int flags) {
159159
public FlecsObserver iter(Query.IterCallback callback) {
160160
this.iterCallback = callback;
161161

162-
final Iter[] iterHolder = new Iter[1];
162+
final ThreadLocal<Iter> iterHolder = new ThreadLocal<>();
163163
MemorySegment callbackStub = ecs_iter_action_t.allocate(it -> {
164-
if (iterHolder[0] == null) {
165-
iterHolder[0] = new Iter(it, this.world);
164+
Iter iter = iterHolder.get();
165+
if (iter == null) {
166+
iter = new Iter(it, this.world);
167+
iterHolder.set(iter);
166168
} else {
167-
iterHolder[0].setNativeIter(it);
169+
iter.setNativeIter(it);
168170
}
169-
callback.accept(iterHolder[0]);
171+
callback.accept(iter);
170172
}, this.world.arena());
171173

172174
ecs_observer_desc_t.callback(this.desc, callbackStub);
@@ -177,14 +179,16 @@ public FlecsObserver iter(Query.IterCallback callback) {
177179
public FlecsObserver run(Query.RunCallback callback) {
178180
this.runCallback = callback;
179181

180-
final Iter[] iterHolder = new Iter[1];
182+
final ThreadLocal<Iter> iterHolder = new ThreadLocal<>();
181183
MemorySegment callbackStub = ecs_run_action_t.allocate(it -> {
182-
if (iterHolder[0] == null) {
183-
iterHolder[0] = new Iter(it, this.world);
184+
Iter iter = iterHolder.get();
185+
if (iter == null) {
186+
iter = new Iter(it, this.world);
187+
iterHolder.set(iter);
184188
} else {
185-
iterHolder[0].setNativeIter(it);
189+
iter.setNativeIter(it);
186190
}
187-
callback.accept(iterHolder[0]);
191+
callback.accept(iter);
188192
}, this.world.arena());
189193

190194
ecs_observer_desc_t.run(this.desc, callbackStub);

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

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,9 @@ public <T> SystemBuilder read(Class<T> componentClass) {
187187
public FlecsSystem iter(Query.IterCallback callback) {
188188
this.iterCallback = callback;
189189

190-
final Iter[] iterHolder = new Iter[1];
191190
MemorySegment callbackStub = ecs_iter_action_t.allocate(it -> {
192-
if (iterHolder[0] == null) {
193-
iterHolder[0] = new Iter(it, this.world);
194-
} else {
195-
iterHolder[0].setNativeIter(it);
196-
}
197-
callback.accept(iterHolder[0]);
191+
Iter iter = new Iter(it, this.world);
192+
callback.accept(iter);
198193
}, this.world.arena());
199194

200195
ecs_system_desc_t.callback(this.desc, callbackStub);
@@ -205,14 +200,16 @@ public FlecsSystem iter(Query.IterCallback callback) {
205200
public FlecsSystem run(Query.RunCallback callback) {
206201
this.runCallback = callback;
207202

208-
final Iter[] iterHolder = new Iter[1];
203+
final ThreadLocal<Iter> iterHolder = new ThreadLocal<>();
209204
MemorySegment callbackStub = ecs_run_action_t.allocate(it -> {
210-
if (iterHolder[0] == null) {
211-
iterHolder[0] = new Iter(it, this.world);
205+
Iter iter = iterHolder.get();
206+
if (iter == null) {
207+
iter = new Iter(it, this.world);
208+
iterHolder.set(iter);
212209
} else {
213-
iterHolder[0].setNativeIter(it);
210+
iter.setNativeIter(it);
214211
}
215-
callback.accept(iterHolder[0]);
212+
callback.accept(iter);
216213
}, this.world.arena());
217214

218215
ecs_system_desc_t.run(this.desc, callbackStub);

0 commit comments

Comments
 (0)