@@ -18,7 +18,7 @@ private static final class Holder{private static final PlayerPosIPC INSTANCE = n
1818 private static final int MAX_SLOTS = 64 ;
1919 // UUID + serverHashCode + worldHashCode + x + y + z
2020 public static final int DATA_SIZE = 16 + 8 + 8 + 8 + 4 + 4 ; //=48
21- // PID + TS + lock + data
21+ // PID + TS + version + data
2222 private static final int SLOT_SIZE = 8 + 8 + 8 + DATA_SIZE ;
2323 // Treat PID as "dead" if no update for > 15s
2424 private static final long TIMEOUT_NS = 15_000l * 1000000l ;
@@ -61,7 +61,7 @@ private PlayerPosIPC(){
6161 throw new ExceptionInInitializerError (e );
6262 }
6363 Runtime .getRuntime ().addShutdownHook (new Thread (()->{
64- // Mark owner PID as -1 so others can take it immediately (rather than waiting for heartbeat)
64+ // Mark as dead so others can take this slot immediately (rather than waiting for heartbeat)
6565 final int base = mySlot *SLOT_SIZE ;
6666 if (buffer != null && myPID == (long )LONG_HANDLE .getVolatile (buffer , base )) freeSlot (myPID , base );
6767 }));
@@ -73,8 +73,7 @@ private final int claimSlot(){
7373 for (int i =0 ; i <MAX_SLOTS ; ++i ){
7474 final int base = i *SLOT_SIZE ;
7575 final long owner = (long )LONG_HANDLE .getVolatile (buffer , base );
76- final long lastHeartbeat = (long )LONG_HANDLE .getVolatile (buffer , base + TIME_OFFSET );
77- if (owner > 0l && now - lastHeartbeat < TIMEOUT_NS ) continue ;
76+ if (owner > 0l && now - (long )LONG_HANDLE .getVolatile (buffer , base + TIME_OFFSET ) < TIMEOUT_NS ) continue ;
7877 LONG_HANDLE .setVolatile (buffer , base + TIME_OFFSET , now ); // Update ts (reduces contention fighting for this slot)
7978 if (LONG_HANDLE .compareAndSet (buffer , base , owner , myPID )) return i ; // Nice, we snagged this slot!
8079// i=-1; // Another PID grabbed the slot before us; start again from i=0.
@@ -98,17 +97,21 @@ public final void postData(final byte[] data){
9897 }
9998
10099 public final void readData (final Consumer <byte []> consumer ){
101- final long now = System .nanoTime ();
100+ final long now = System .nanoTime (), prevOwner ;
102101 for (int i =0 ; i <MAX_SLOTS ; ++i ){
103102 final int base = i *SLOT_SIZE ;
104- final long owner = (long )LONG_HANDLE .getVolatile (buffer , base );
103+ final long owner = (long )LONG_HANDLE .getOpaque (buffer , base );
105104 if (owner < 0l || owner == myPID ) continue ;
106- if (owner == 0l ) return ;
107- final long lastHeartbeat = (long )LONG_HANDLE .getVolatile (buffer , base + TIME_OFFSET );
108- if (now - lastHeartbeat > TIMEOUT_NS ){freeSlot (owner , base ); continue ;}
105+ if (owner == 0l ){
106+ // Attempt cleanup of trailing -1/-2 for the last slot before 0
107+ if (i > 0 && (prevOwner =(long )LONG_HANDLE .getVolatile (buffer , base -SLOT_SIZE )) < 0l ) freeSlot (prevOwner , base -SLOT_SIZE );
108+ return ;
109+ }
110+ if (now - (long )LONG_HANDLE .getVolatile (buffer , base + TIME_OFFSET ) > TIMEOUT_NS ){freeSlot (owner , base ); continue ;}
109111// while(((long)LONG_HANDLE.getAcquire(buffer, base + VERSION_OFFSET)&1) == 0) Thread.onSpinWait();
110112 final long version = (long )LONG_HANDLE .getAcquire (buffer , base + VERSION_OFFSET );
111113 if ((version &1l ) == 0l || version == lastReadVersions [i ]) continue ; // Skip busy or stale
114+ VarHandle .fullFence ();
112115 buffer .get (base + DATA_OFFSET , data ); // Read data
113116 if (version == (long )LONG_HANDLE .getVolatile (buffer , base + VERSION_OFFSET )){ // Verify data wasn't altered mid-read
114117 consumer .accept (data );
0 commit comments