[Forum] My topic is not available at page 3 only?!

Hi, I have an open discussion at: http://hub.jmonkeyengine.org/forum/topic/support-request-mac-os-retina-crash-with-jmeswing
and all the pages can be accessed except for page 3, which is the last one as I get “Service Unavailable”: http://hub.jmonkeyengine.org/forum/topic/support-request-mac-os-retina-crash-with-jmeswing/page/3/

I really need to write there as I need to detect and fix the bug to finish my software. It seems it’s caused by PaintMode.ACCELERATED and I need to write it so the guys who are helping me can give me more info about it.

Thanks,
Axel

The forum has some bug where some piece of content causes the page to be undisplayable. It only occurs if you are logged in, actually… so if you just need to see the old posts you can log out first.

It’s a pain.

@pspeed said: The forum has some bug where some piece of content causes the page to be undisplayable. It only occurs if you are logged in, actually... so if you just need to see the old posts you can log out first.

It’s a pain.

Thanks for the explanation, but I need to go on with the discussion, not checking the previous posts. I have found that if AWTPanel uses PaintMode.Accelerated, it will cause a deadlock. But if PaintMode.Repaint is used, the scene will go on jerking (like fast flashes in the scene) but at least it won’t cause the deadlock. Something is wrong in the AWTPanel class when using PaintMode.Accelerated…

@AXELTOPOLINO said: Thanks for the explanation, but I need to go on with the discussion, not checking the previous posts. I have found that if AWTPanel uses PaintMode.Accelerated, it will cause a deadlock. But if PaintMode.Repaint is used, the scene will go on jerking (like fast flashes in the scene) but at least it won't cause the deadlock. Something is wrong in the AWTPanel class when using PaintMode.Accelerated...

Since it sounds like it’s using hardware acceleration then it may be because you’ve blocked paint() that you are inadvertently blocking the render thread… thus JME will never process your Callable and so your block will never be released.

As I said before, your life will be easier if you do this fully asynchronous. Enqueue the callable and then don’t watch. Have the callable use SwingUtilities.invokeLater() to notify you. I mean, I don’t know if this is fully possible because I didn’t really look at why you are waiting but the cases where asynch message passing can’t be used are so rare.

1 Like
@pspeed said: Since it sounds like it's using hardware acceleration then it may be because you've blocked paint() that you are inadvertently blocking the render thread... thus JME will never process your Callable and so your block will never be released.

As I said before, your life will be easier if you do this fully asynchronous. Enqueue the callable and then don’t watch. Have the callable use SwingUtilities.invokeLater() to notify you. I mean, I don’t know if this is fully possible because I didn’t really look at why you are waiting but the cases where asynch message passing can’t be used are so rare.

Ok I’ve probably missed the asynchronous part: could you write pseudocode to show what you mean, please? Because I have always watched the callables so far to get their values.
Do you mean something like enqueueing the callable and use invokeLater() inside?
Thanks pspeed and hope the forum will be fixed soon :slight_smile:

Synchronous = you wait for the response.

Asynchronous = you don’t wait for the response but instead pass a message back later.

@pspeed said: Enqueue the callable and then don't watch. Have the callable use SwingUtilities.invokeLater() to notify you.
@pspeed said: Synchronous = you wait for the response.

Asynchronous = you don’t wait for the response but instead pass a message back later.

I understand this is a bit annoying, but I’m still trying to get what you mean:
We have a boolean variable in the JME thread.
We start and initialize the JME app.
We use invokeLater() right after and wait until the JME app is ready (using wait/notify).
We need to know the value of that boolean variable in order to draw a Swing component (so we need it in the paintComponent() method enqueueing a callable and watching for that value).
This provokes a deadlock because of the AWT Panel PaintMode.Accelerated.

Now, I still don’t get how we can enqueue a callable and use invokeLater() inside it to get that variable.
Don’t kill me please :smiley:

EDIT: Wait a second: you mean using invokeLater() in paintComponent() to avoid blocking the EDT task and adding the actual painting of the component as very last task (so it doesn’t block any previous)?

Well, if it’s just a shared boolean then use AtomicBoolean to set it from JME and check it from Swing… problem solved. No messaging needed. No reason to force block on transient state I guess.

Though I honestly didn’t see what the boolean was for because I wasn’t looking. So maybe that’s problematic for some other reason?

@pspeed said: Well, if it's just a shared boolean then use AtomicBoolean to set it from JME and check it from Swing... problem solved. No messaging needed. No reason to force block on transient state I guess.

Though I honestly didn’t see what the boolean was for because I wasn’t looking. So maybe that’s problematic for some other reason?

The problem is not the boolean, because we actually need to call some other objects aswell that cannot be “Atomic” (a node for example).
Also using the invokeLater() inside the paintComponent() methods avoids the deadlock, but the custom panel doesn’t render as expected (seems it renders other parts of the GUI and it is because we are painting as last task?) :S

PS: this is how I’m using the paintComponent() of the custom panel:


   @Override
    protected void paintComponent(final Graphics g) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                render(g);
            }
        });
    }

    protected void render(Graphics g) {
        draw rectangles();//draws some custom rectangles
        super.paintComponent(g);
    }

Well, if you are doing more than checking a boolean then obviously you will need to do more… but I’m also not sure why your mentioned it then. :-/

The idea behind double async is to do double async pretty much word for word what I described but I will go into more detail now.

In your Callable. The one you enqueue for JME to run. The one you enqueue from the Swing thread. Just enqueue it. Don’t do anything else. Don’t wait for it. Just keeping going. Do not call get() on it. Do not block. Blocking is bad. Don’t block.

Use some local state that has not been set yet to decide what you should do next.

In the Callable. The one that is run on the JME thread. The one that you enqueued above. Call SwingUtilities.invokeLater() with a runnable (that will be run on the swing thread and not on the JME thread) that calls your Swing-related class with whatever data it needs. This will be on the swing thread and not the JME thread so you should be able to access any swing related stuff including having yourself repaint if needed.

Again, as I said before in different words:

@pspeed said: Enqueue the callable and then don't watch. Have the callable use SwingUtilities.invokeLater() to notify you.

Note the specific mention of the callable calling SwingUtilities.invokeLater().

From a high level in english:
Your class on the EDT doesn’t know what state the scene graph is in so it sends an e-mail to JME.

JME receives the e-mail, types up a response, and sends it back to the EDT.

Your class on the EDT receives the e-mail then has a chance to do other stuff… like repaint, set a local variable, whatever.

No one waited for anything.

1 Like

@pspeed: Many many thanks for your explanation. I still don’t actually get why the EDT should be blocked enqueueing objects, but with your method the software works again and can do almost everything it used to do. I now have only 2 weird bugs, which I suspect are caused by the AWT Panel (with the Canvas these didn’t happen):

  1. My geometries uses transparency, but if I do:

geom.setQueueBucket(RenderQueue.Bucket.Translucent); 

my geometries just are invisible (my color is gray with Alpha at 50% and it was perfect previously)

  1. I’m using a ShootSelectionListener to select the geometries using CollisionResults. It used to work fine with the Canvas, but now it find collisions like if the geometry is moved from the right place (for ex. I need to select above my geometry in the air to select that geometry).

I think this could be because of how the AWT Panel is coded, but it’s just a guess.
Are they known bugs or am I missing some important details? :S

Again, many thanks!

@AXELTOPOLINO said: @pspeed: Many many thanks for your explanation. I still don't actually get why the EDT should be blocked enqueueing objects, but with your method the software works again and can do almost everything it used to do. I now have only 2 weird bugs, which I suspect are caused by the AWT Panel (with the Canvas these didn't happen): 1. My geometries uses transparency, but if I do:

geom.setQueueBucket(RenderQueue.Bucket.Translucent); 

my geometries just are invisible (my color is gray with Alpha at 50% and it was perfect previously)

  1. I’m using a ShootSelectionListener to select the geometries using CollisionResults. It used to work fine with the Canvas, but now it find collisions like if the geometry is moved from the right place (for ex. I need to select above my geometry in the air to select that geometry).

I think this could be because of how the AWT Panel is coded, but it’s just a guess.
Are they known bugs or am I missing some important details? :S

Again, many thanks!


I just fixed those two issues in git master. Unfortunately, you may need to wait until jME3.1 is released for those fixes …

@AXELTOPOLINO said: @pspeed: Many many thanks for your explanation. I still don't actually get why the EDT should be blocked enqueueing objects

It was blocked because you blocked it. It wasn’t the enqueue. You blocked the EDT waiting for a result from the callable. In the mean time, because you were using hardware acceleration on swing, I’m guessing that JME never got a chance to run… and so was never going to run that callable. Just a guess, though.

The problem with synchronous calls like the way you had it is that you have to understand and keep in mind way too many things about the whole application. It’s fragile and adds coupling that shouldn’t need to be there. In this case, you had a side effect where blocking the EDT was also blocking JME… thus a virtual deadlock.

When you write fully asynchronous code you only need to worry about how that code runs and not the whole application. Sometimes it can be a little tricky to write but at least there are relatively few hidden side effects waiting to pop out later.

@pspeed said: It was blocked because you blocked it. It wasn't the enqueue. You blocked the EDT waiting for a result from the callable. In the mean time, because you were using hardware acceleration on swing, I'm guessing that JME never got a chance to run... and so was never going to run that callable. Just a guess, though.

The problem with synchronous calls like the way you had it is that you have to understand and keep in mind way too many things about the whole application. It’s fragile and adds coupling that shouldn’t need to be there. In this case, you had a side effect where blocking the EDT was also blocking JME… thus a virtual deadlock.

When you write fully asynchronous code you only need to worry about how that code runs and not the whole application. Sometimes it can be a little tricky to write but at least there are relatively few hidden side effects waiting to pop out later.

Thanks, it seems I have worked too much on single-threaded apps, I will try to avoid synchronous calls in future :slight_smile:

@Momoko_Fan said: I just fixed those two issues in git master. Unfortunately, you may need to wait until jME3.1 is released for those fixes ...

Oh gosh, happy to know that they are fixed, but is there a release date for JME3.1? Because I’ve already released the 1st version of the software and many people are waiting for this fix :S

…or at least is there any workaround I can do to temporanely fix it in JME 3.0? Like editing the JME code temporanely or something like that :slight_smile:

You can tell us even bad things guys, but we really need to know an answer on any of my questions (I know asking for ETAs is annoying as hell, but right now people are doing the same thing to me because they are waiting for the editor I am working on). I’d actually need a temp workaround, nothing more :slight_smile:

@AXELTOPOLINO said: You can tell us even bad things guys, but we really need to know an answer on any of my questions (I know asking for ETAs is annoying as hell, but right now people are doing the same thing to me because they are waiting for the editor I am working on). I'd actually need a temp workaround, nothing more :)
We don't really have nightly releases working for either stable or 3.1 so those changes are only available in the source code. Our build server was taken down due to security holes and we don't really have a replacement yet. The new site is supposed to have some build capability but at this point things are still in motion and nobody knows anything ... The easiest thing would be to just apply them against the 3.0 stable source code and recompile.

As for jME3.1 release date … Its such a good secret that even I don’t know what it is!

@Momoko_Fan said: We don't really have nightly releases working for either stable or 3.1 so those changes are only available in the source code. Our build server was taken down due to security holes and we don't really have a replacement yet. The new site is supposed to have some build capability but at this point things are still in motion and nobody knows anything ... The easiest thing would be to just apply them against the 3.0 stable source code and recompile.

As for jME3.1 release date … Its such a good secret that even I don’t know what it is!


Thanks Momoko_Fan,
I really appreciate your clear and honest explanations (and I also appreciate JME a lot :slight_smile: ).
Would you be so kind to show me the edits you have done on git master about the 2 AWT Panels fixes? I’ll do the edits in the 3.0 code and try to recompile it as you suggested!

Have both the fixes been made in the AWTPanel class? Or did you edit other classes in the JME code? Just knowing which classes would be enough for me :slight_smile:

There are changes to AwtPanel and AwtPanelsContext classes:
https://github.com/jMonkeyEngine/jmonkeyengine/commit/595183fb64479b87804068eab506065471e1ed50.diff

And also AwtMouseInput:
https://github.com/jMonkeyEngine/jmonkeyengine/commit/ec6befeeaa077a95cb018bd2c7a746cd6ccf3cbb.diff

Note that you won’t be able to apply them to the root folder of the 3.0 source tree since the build system and all paths changed, you will need to apply to the files directly.