How to prevent modifying Spatial out of main thread?

@pspeed may be, this option below may be useful to slap newbies faces to implement their (my) code properly :smile: , now, instead of checking for root node or gui node, the aim is towards modification after rootNode.updateGeometricState() and BEFORE the rendering ends. But… the randomicity of that access may prove it is actually worthless. Unless I can find a way to create a thread.sleep() for the other threads whenever the rendering is being performed?

@Empire_Phoenix (about this post where your code seems to provide a way to completely block access to Node methods outside of openGLThread / rendering / mainThread, as long assertion is enabled!)

Cant wait to test it!

Btw, Interestingly enough, I had created a patcher to Spatial.java and other files (using linux sed) that focused on placing the thread check everywhere the refreshFlags variable got modified, just before it, but it always had CPU usage, not like yours, and… it could be more precise as I explain below:

# create the function to be placed where it is important
sed -i.bkp -r 's@private static final Logger logger@protected void assertMainThread(){if(!Thread.currentThread().getName().matches("main|jME3 Main"))throw new NullPointerException("FORBIDDEN modification of spatial outside of main thread!!!");}\n\t&@' ./src/com/jme3/scene/Spatial.java
# place the function at several files matching refreshFlags modification
find ./src/ -type f -iname "*.java" -exec sed -i -r 's@[^[:blank:]/]*[.]{,1}refreshFlags[[:blank:]][|&]=@assertMainThread();&@' {} +
# show the modifications (disabled sed backups above as would create even for unmodified files)
grep assertMainThread ./src/* -irnI

So re-reading the exception message at Spatial.checkCulling():

Scene graph is not properly updated for rendering.\n
State was changed after rootNode.updateGeometricState() call. \n
Make sure you do not modify the scene from another thread!\n
Problem spatial name:

Concerning precision: As I understand, in therms of synchronization, even if I shouldnt, I “can” modify the scene from another thread, as long it happens before rootNode.updateGeometricState(), or after the rendering step completes (right?).

So again with your code, with assertion enabled, we can track if we implemented some Node method access outside of main thread right?
But I believe we could be more flexible and restrict only a few methods using a mix of the code you provided and the sed patcher I made.

  • The problem I still didnt manage to work around is how to synchronize that check to throw exception/assertion only if refreshFlags modification happens AFTER rootNode.updateGeometricState() and BEFORE the rendering ends… But, if the modification happens in a random moment (most probably) it will not be a good access at all, therefore your code will be the best option per se, as we cant grant anything under this kind of randomicity. Unless we can find a way to create a thread.sleep() for the other threads whenever the rendering is being performed? I think such sleep, must happen at every attempt to modify refreshFlags, therefore at assertMainThread(), but I feel it must be a kind of atomic/single/synchronized access implementation, what may clog the main thread and be a bad thing after all…

PS.:
Also, I looked for ThreadSaveNode everywhere here: empirephoenix · GitHub
Can I add it to my project under BSD license?
By what you coded, it looks like we have to determine what nodes will have that checker by instancing them with ThreadSaveNode, so basically I understand that suffices (instead of replacing/patching Node.java, or may be using some kind of classloader trick :)).