Bug 898

Summary: Can't control Animator from EDT/Animator thread - notifyAll() not always called in AnimatorBase.finishLifecycleAction(..)
Product: [JogAmp] Jogl Reporter: Sven Gothel <sgothel>
Component: coreAssignee: Sven Gothel <sgothel>
Status: RESOLVED FIXED    
Severity: enhancement CC: sgothel
Priority: ---    
Version: 2   
Hardware: All   
OS: all   
Type: --- SCM Refs:
3e1924e73d583d344b45839bed3a7bd51751a019
Workaround: ---

Description Sven Gothel 2013-11-07 09:58:05 CET
Copied from forum post:
  <http://forum.jogamp.org/Can-t-control-Animator-from-EDT-Animator-thread-tp4030500.html>
from 'kosukek' [via jogamp]

+++

In our application we play short animations on GLCanvas here and there, but most of the time the canvas remains static and doesn't require frequent repaints. We use Animator class to refresh the canvas during an animation, then after a while Animator.pause() is called to go back to static mode.

We've been using JOGL v2.0-r11 for about a year now and it's been working quite well. However since v2.0.2 when Animator.start()/stop()/pause()/resume() is called on EDT/Animator thread it doesn't seem to work. Had a quick look at AnimatorBase.finishLifecycleAction() and probably the difference from v2.0-r11 might be that notifyAll() is not always called. On v2.0-r11, it seems notifyAll() is unconditionally called once at least.

Here's a snippet to reproduce the issue. On v2.0-r11, this repeats animation cycle. On v2.0.2 or higher, calling Animator's member methods generates exceptions and resume() won't restart the cycle as expected(tested on JDK6/7, Windows x64).

public class NewJFrame extends javax.swing.JFrame {

    static {
        System.setProperty("jogl.debug.Animator", Boolean.TRUE.toString());
    }

    public NewJFrame() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        //Layout
        setMinimumSize(new Dimension(100, 100));
        getContentPane().setLayout(new BorderLayout());
        GLCanvas panel = new GLCanvas();
        getContentPane().add(panel, BorderLayout.CENTER);
        pack();
        //Animator
        final Animator animator = new Animator();
        animator.add(panel);
        //GLEventListener
        panel.addGLEventListener(new GLEventListener() {
            long startTime = System.nanoTime();

            @Override
            public void init(GLAutoDrawable glad) {
            }

            @Override
            public void dispose(GLAutoDrawable glad) {
            }

            @Override
            public void display(GLAutoDrawable glad) {
                System.out.println("display()");
                long time = System.nanoTime();
                if (animator.isAnimating() && time - startTime > 100e6) {
                    animator.pause();
                    System.out.println("animator.pause()");
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            if (animator.isPaused()) {
                                startTime = System.nanoTime();
                                animator.resume(); //Doesn't work on v2.0.2 or higher
                                System.out.println("animator.resume()");
                            }
                        }
                    });
                }
            }

            @Override
            public void reshape(GLAutoDrawable glad, int i, int i1,
                    int i2, int i3) {
            }
        });
        //Start animation
        animator.start();
        System.out.println("animator.start()");
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new NewJFrame().setVisible(true);
            }
        });
    }
}


I am wondering if we should avoid using Animator altogether in this kind of situation. I understand NEWT should do a better job but we need to stick to GLCanvas for now.

Sincerely,

+++
Comment 1 Sven Gothel 2013-11-07 11:34:54 CET
3e1924e73d583d344b45839bed3a7bd51751a019
Apply best efford on Animator operation's finishLifecycleAction(..) in !blocking mode, i.e. notifyAll() if waitCondition holds and test again