Threading model

Greetings all,

Thanks a lot for a great product and superb support in this forum. Almost every issue I’ve had has been explained in great details in these forums.

I have a question that may be more oriented towards experience than the underlying architecture of Xith3D+JOGL. From my experience using Xith3D I have seen there are two main models when implementing timeslicing for a project:

The ‘more Java’ way is to use separate threads threads that (for example) modify a Transform3D in the background to make a cube spin. This approach has the benefit that the timeslicing is performed by the VM or (hopefully) the OS. But in task intensive applications, or where synchronization is very important it may prove ‘inexact’ and very resource consuming.

The othe way, the GL way, is to implement a single thread model where we give time to each component for it’s calculations. This is a little less ‘object oriented’ in Java’s way, but has the advantage of providing a scalable and ‘perfectly-synchronizable’ experience.

In the project I’m working on I’ve implemented both models, having a simple way to switch between one or the other easily at runtime. I still have not used any huge scene, so it’s literally impossible to tell the one from another. But I’m interested in your opinions (as developers and users of Xith3D) on how do you implement time-slicing and what your experiences are.

Thanks again for a great tool and a better community.

In gaming, I never saw a real need to have multiple threads. Theres always a clear place where updates should take place.

Most game engines (like Renderware) aren’t threadsafe.

And making (and keeping) Xith3D threadsafe won’t be that easy?

Hello,

Xith3D is not thread-safe, and this is a design decision. I use Xith3D in multithreaded applications, but I use special mechanisms to ensure that I do not make concurrent modifications of Scenegraph.

Synchronization is done on single lock object, so rendering thread can not enter renderOnce() while another modifies scenegraph.

Scenegraph modification thread performs all the calculations without holding a lock, and synchronizes only to copy consistent computation results to a scenegraph. This also ensures that scenegraph reflects single point of time at any given moment, and two objects from different points of time can not be rendered in one frame.

But, anyway, this mechanism is application-specific, so developers can choose the sync schema they want.

Yuri

In the past, i was using two threads (not in combination with Xith, but that doesn’t matter). One was doing the rendering, while the other one was doing the “physics” (movement of the player, objects and, most important, collision detection). This was a bad idea on dual processor/hyper threading machines because i ran into threading issues (obviously…using a matrix in the rendering that another thread is modifying isn’t a good idea… :wink: ). Somehow it worked fine on single processor machines.
Anyway, i’ve replaced that approach with this: I’m now doing movement, collision detection and rendering in one thread. I’m counting the number of “ticks” that have passed since the last frame…and here lies the problem: The rendering time doesn’t depend on the number of ticks passed, just on the geometry…so far, so good.
But the collision detection is different: When using a swept ellipsoid approach, the time the algorithm takes depends on the length of the translation vector. If a lot of collisions are taking place, the collision detection may take (for example) 1 tick. Then comes the rendering which takes another tick. So the next time you enter the collision detection, 2 ticks have passed since the last time. But that will most likely increase the time the collision detection takes…let’s say it takes 2 ticks now and still one for the rendering. Then you are at 3 ticks the next time the collision detection is called. Then it takes 3 ticks, the rendering 1 and you are at 4 and so on. Finally, you end up with a gazillion of ticks spend in the collision detection and framerate can be measured in seconds per frame.
Of course, this is a simplyfied description of the problem, but i ran into it when doing collision detection which a larger amount of objects that are all colliding with each other and i don’t have a good idea how to solve this in a general way, except to ignore the ticks spend in the collision detection, which will cause the movement to slow down in extreme situations. Any other ideas?

In fact being thread safe would cause a lot of work that could be spent elsewhere. I simply like to compare this question with the event handling in Swing. Though it is 2D it has never been threadsafe at all. You may know what happens if you are changing one JComponent and the event handling redraws an old state. There they are using SwingUtilities.invokeLater() to ensure that your work will be done after any previous change - it is a kind of serialization. This does not mean you cannot have many threads but only one for updating/changing the view.

Back to 3D again it could make sense to have a thread for each object that may change/be transformed (e.g. a clock that requries an update every second without counting ticks but a thread sleeping in the meantimeand so on) but IMHO you will end with one thread for updating your graphics at least.

Also as it was mentioned in this thread before you may have to handle synchronization issues especially if you do rely upon exact timings and positions. Therefore I think that positioning of objects is well located in the update thread whereas precalculation of changed forms etc. can be done in an own thread unless it is required for collison detection or so on.

Stefan

Why not to use a lock object?

If a thread wants to modify the Scenegraph, it then class a “lock()” method on our lock object, and “unlock()” when done. The call of lock on concurrent access force the calling thread to sleep if scenegraph already in use.

It’s simple, fast and does not consume any resource to put in place.

Hi,

[quote]Why not to use a lock object?
[/quote]
On the application level - yes, it can be used. Inside scenegraph - no, to achieve nice synchronization we would have to put a lot of locks/unlocks, and this will eat a lot of performance.

renderOnce() method is already synchronized against its View instance, so if you write something like

View view = ...
...
synchronized(view)
{
   modifyMyScenegraph();
}

you can say that modifyMyScenegraph() will never be called when renderOnce() is executing.

Yuri