Client/Server Threading Models

I just read the docs on the jME3 Threading Model and see the following two sentences:

If you make changes only in Control.update(), AppState.update(), or SimpleApplication.simpleUpdate(), this will happen automatically. However, if you pass work to another thread, you may need to pass results back to the main jME3 thread so that scene graph changes can take place there.

I’m just looking to make sure I understand the threading model correctly here:

  • It seems as though there is a “main thread” where the app’s main method is called
  • There is a separate thread where the SimpleApplication#simpleUpdate loop is run (what’s this thread called?). This is also where the scenegraph runs out of.
  • Each Custom Control instance is placed in its own thread, and its update method is continuously called inside that control’s dedicated thread
  • An isolated App State thread is also maintained

Are my assumptions correct or am I way off base? Am I missing any other important threads? Are there “client-only” and “server-only” threads that I should be aware of?

Way off :slight_smile: There’s only one jme thread, and only one update loop which traverses the whole scenegraph and calls all Controls. The app states are also called in this loop.

To make changes to the scenegraph you have to inject your code into this jme thread (only if you’re not already there, which probably is the case if you do your stuff inside update() methods).

2 Likes

Thanks @1000ml

Is there documentation which shows the order in which everything is called? Something like:

  1. Run SimpleApplication#simpleUpdate
  2. Run all Custom Control instances’ update methods
  3. Run AppState.update
  4. Update scenegraph

…or something like that? Just wondering what the ordering was for all these (seemingly) disparate update methods. Thanks in advance!

I have never really needed to care too much about order. But if i did i would look at the source.

Thanks @delt0r I think I can live with that :slight_smile:

Just for clarity’s sake though: I’m still a wee bit fuzzy on the relationship of the scenegraph to all of these update methods. In these update methods, specific spatials can be transformed (rotated, scaled, relocated, etc). Is the scenegraph mutated lazily (perhaps one time, after all of these update methods run), or is the scenegraph mutated on-the-fly, as each transformation is executed?

Yeah, I recommend you make a habit of looking at the code. It’s nicely written.
Here’s a starting point: jmonkeyengine/SimpleApplication.java at master · jMonkeyEngine/jmonkeyengine · GitHub

Changes to objects are applied immediately. If multiple Controls work on the same Spatial, you could use relative transformations (Spatial.move()), so order shoudln’t be a problem.

Or rather… the interesing changes happen immediately. There are certain updates that happen once per cycle, lazily.
update geometric state, bounding volume update, stuff like this. But I think in general you don’t have to care about that.

It is perhaps a good idea to have only one to one control.

Remember that the scene graph defines the View. ie it is not the model (MVC pattern). That is your game state shouldn’t be clustered and tied into the scene graph (ie the view).

MVC stands for Model View Controller design pattern. You really want to look that up if you don’t know it already. If you only ever learn one design pattern learn this one.

1 Like

You can see a full network base example (that uses SimEthereal for real-time object synching but that’s sort of a side note)… here:

And Entity System version (Entity Component System) of that same demo is here:

Those both follow JME best practices to the best of their ability… including how to use AppStates to manage things, receiving network messages, etc…

Thanks everyone! And thanks for the example projects @pspeed - looking at those two projects, I have several questions about your project structure and code conventions. Is it OK to ask those questions here, or do you want me to create GitHub issues, or ask them somewhere else? (Or do you not want me to ask any questions about them at all!?)

Thanks again!

You can ask them here.

Thanks!

So looking at your SimEthereal code base @pspeed, you make extensive use of app states.

I read the doc on App States, and I think I’m not quite seeing the “forest through the trees” here. It seems like App States allows you to turn your game into a state machine, where each state is perhaps a different/distinct scenegraph with its own/distinct game objects. And that when you transition to a different state, essentially the scenegraph and game objects associated with that state all get paused, and the new state is initialized/resumed.

Is that (more or less) correct, or am I way off base? Thanks again!

Nope.

It’s better said that AppStates are a way of “extending” the functionality of application through composition instead of inheritance. And that “extending” can be temporary.

Generally, one should always prefer composition over inheritance.

Edit: and if you write your AppStates properly then many of them can be reused across many games.

Hmmmm, are you maybe saying that App States are meant to “extend” the SimpleApplication class? Any chance you can give a concrete example of a use case for an App State (the description in the jME3 docs, to me, is a wee bit vague/generic)?

For example, let’s take your SkyState, what exactly is that used for? Why make it an AppState? A concrete example like that will make all the light bulbs go off (or explode). Thanks!

My app states are concrete examples. The sky state adds a sky to the scene. Remove the app state again (or disable it) and the sky goes away. I can use that sky state with any application where I want stars in the background. (And it would be easy enough to modify to work with any images.)

The main menu state is active while the main menu is open. It handles the input for the main menu.

I mean, the names of these states are pretty self-explanatory I thought and the code for them is not complicated. AppStates have a specific lifecycle. You override/implement these methods to do things at those times. That lifecycle is covered in the AppState and AppStateManager javadocs.

Ahh so why did you choose an AppState to manage your sky spatial, and not a Custom Control (why does SkyState extend BaseAppState instead of AbstractControl)? Meaning, what’s the difference between App States and Custom Controls, and under what scenarios do you recommend using either of them?

I ask because based on my understanding of Custom Controls (per the docs), a Custom Control’s job is to manage a spatial, so I’m wondering why you’re managing your “sky” spatial via App State instead? Not being critical at all here, just trying to learn from you so I can implement similar designs in my stuff!

A control manages a spatial, that is correct. An app state instead can go way further: it can modify the whole scene graph. So in the example of the sky you would need an app state because you need to attach the sky spatial to the scene. Or phrased differently: a control can’t attach itself to the scene.

I see it that way:
App State: modify the scene graph. The important action happens when the state is attached or detached.
Control: per-frame modifications to a specific spatial, independent of where it is in the scene graph.

Some more examples from one of my projects:

  • flickering light → control that changes the light position + radius with some noise every frame
  • wireframes → an app state that adds/removes a processor forcing the wireframe material when it is attached/detached

Thanks @shamanDevel that makes sense.

Controls don’t have access to the application, assetManager, anything but the spatial really. That makes their use extremely limited.

If you want to extend the behavior of a single already loaded spatial then a Control is a good idea.

If you want to do just about anything else then an AppState is better.