[SOLVED] Challenges in multithreaded mutable world design

First off, not really sure where to post this, as it involves rendering, networking, and multithreading. So here I am general topics!



Context; I’m attempting to build a fully mutable sandbox world from the ground up to be both networked and multithreaded for best scaling performance possible on higher end hardware. The system uses a client / server relationship for networking.



I hit a snag with multithreading, found an interesting fix, and would like to investigate it’s ramifications with all of you. The snag was concurrent modification of the world data (rootNode) from multiple threads. I know this is strictly not allowed by the OpenGL render thread. But I was curious and found that if I ran the program in headless server mode (as my server would be) the exception went away.



Now I’d also like to use assertions for development purposes, but I found that with assertions enabled my program still crashes as an assertion is checking for the concurrent modification problem even when in headless server mode.



Is it ‘cheating’ to allow concurrent access to the rootNode when in headless server mode? Will this approach lead to other problems down the road, or is really just a concern for the rendering process and thus irrelevant on the server? And is there a way I can get assertions back for my use without the jme crashing my program everytime? Should I comment out those assertions in the engine?



Thanks for reading.

@magister said:
Is it 'cheating' to allow concurrent access to the rootNode when in headless server mode?

It's not cheating, it's wrong and not allowed, hence the exceptions.
Read the multithreading wiki page in great detail before you proceed. If you modify something on the scene on a background thread, you have to enqueue it back onto the openGL thread. Then you won't have these issues.

I may have done a poor job explaining myself. There is no exception. There is an assertion error. There’s a critical difference between the two. Assertions are disabled by default and should not be used to enforce proper use of a class or system. They should only be used to help in debugging.



My program runs in headless server mode without any exceptions being thrown. This implies it is working correctly but as I have no UI I can’t easily check on what is actually going on. I’m working on the client right now so soon I’ll be able to connect to the server and be able to see what’s happening, but that’ll take awhile longer yet.



When I enabled assertions that’s when I got the assertion error. I wasn’t even aware of this for a long time as assertions are normally disabled. If I’m using jme wrong I should have gotten an exception before I ever reached this point. That’s where my confusion is coming from and why I’m posting.



I’ve read this article and many others over several times already with great care. I understand what the ‘right’ way to handle multithreading is, but my concern is one for efficiency. That’s why I’m testing the bounds to gain a better understanding of what can and can’t be done.

Headless might assert instead of throwing an exception, I’m not sure. Either way, it is telling you not to modify an object outside of the render thread without enqueueing it.

It isn’t inefficient to enqueue the item, it gets modified next frame. Much faster than any networking will be able to deal with.

Usualy if you have to do something work intensive with an object that you want to put in another thread then clone the relevant object and when the work is done exchange the previous object with the modiefied one in the update thread. That way update thread only has to flip the object but working on them is done in a seperated thread.



Apart from that you don’t describe your problem detailed enough. Without any example such problems usualy can’t be answered from someone who doesnt know the enviroment :wink:

Personally, I think trying to have a whole scene graph on the server just to manage some game objects is harder in the long run. It’s better to have properly designed server-side data structures that support your threading model… and to actually think about what your threading model will be (some kind of single threaded command dispatch or thread-safe datastructures?)

I was actually just thinking that. I was at first thinking I could implemented a ‘checking-out’ system in which the main thread would remove a particular area from the rootnode, pass it to my threading system to work on, and then when completed add it back to the root node. But that got me thinking, what’s the point of having the root node in the first place then?



I know the rootNode handles rendering the scene. But I don’t need that on the server. So what else does it do? I tested collision checking and ray tracing on nodes not connected to the root and they work. Does jme’s update and control system depend on the rootnode?

Your nodes and spatials need to be attached to have their update and render methods called. But really, the whole headless rendering pipeline seems like wasted effort to me for a server. Even just collision support seems dubious and technically you get that with just Mesh.



If you are using physics then you’d get that sort of thing anyway… and a lot of times you don’t even want mesh-accurate collisions on the server.



There are many ways to architect a server I guess and only one style is conducive to a single update loop approach.

Ok, so I could use jme to program my server (because I love Java) but then I wouldn’t bother using the rootNode. I already have a structure thought up for my world data, so that isn’t a problem. Then I can use meshes for ray tracing and collision without attaching them to the rootNode. And then I’ll want to implement my own updating system in tandem to my multithreading system.

ACtuall you should keep in midn that you cannot use the standart node class then (else it would work) since it is not threadsafe, but the main idea is like that, you maybee (depending on case) dont need a single update method but could do everything event based.

@magister said:
Ok, so I could use jme to program my server (because I love Java) but then I wouldn't bother using the rootNode. I already have a structure thought up for my world data, so that isn't a problem. Then I can use meshes for ray tracing and collision without attaching them to the rootNode. And then I'll want to implement my own updating system in tandem to my multithreading system.


That parts of JME that are most useful to me on the server are: SpiderMonkey and com.jme3.math... and the latter is questionable depending on your architecture. If you use physics then you can use the bullet integration... though if you have a really large expansive world then you will need to pay attention to float precision.

Keeping mesh around just for collisions is ok I guess. I wouldn't do anything with Spatials, really. And most times mesh-level collision is overkill.

...but I don't know what kind of game you are making. JME does have a things built in to deal with collisions and walkmeshes and it would be convenient to keep using these in that case.