Bug 1033 - Guarantee atomicity of high-level GLAutoDrawable operations, avoiding race conditions.
Summary: Guarantee atomicity of high-level GLAutoDrawable operations, avoiding race co...
Status: RESOLVED FIXED
Alias: None
Product: Jogl
Classification: JogAmp
Component: core (show other bugs)
Version: 2
Hardware: All all
: --- major
Assignee: Sven Gothel
URL:
Depends on:
Blocks:
 
Reported: 2014-07-15 04:09 CEST by Sven Gothel
Modified: 2014-07-27 23:26 CEST (History)
2 users (show)

See Also:
Type: DEFECT
SCM Refs:
c77b8f586cb2553582a42f5b90aeee5ef85f1efe
Workaround: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sven Gothel 2014-07-15 04:09:14 CEST
Currently race-conditions are possible on the following 
high level utility method:

- GLDrawableUtil.swapGLContextAndAllGLEventListener(
                    GLAutoDrawable a, GLAutoDrawable b);

- GLEventListenerState.moveFrom(GLAutoDrawable src)
- GLEventListenerState.moveTo(GLAutoDrawable dest)

Their implementation lacks locking of
  [1] the GLAutoDrawable's NativeSurface, as well as of
  [2] the GLAutoDrawable's implementation own 'upstream' lock.

Locking of the NativeSurface is mandatory to hinder other threads
of acquiring the OpenGL context (lock).

Since GLAutoDrawable implementations also employ their own 
'high-level' lock, e.g. for modifying their surface/drawable,
it is important to acquire a lock on such beforehand.

Actual locking order of GLAutoDrawable is:
  1) GLAutoDrawable Lock
  2) NativeSurface Lock

(Note: GLContext.makeCurrent() acquires the NativeSurface Lock 1st.)

Allowing proper locking requires our API to expose 
the GLAutoDrawable 'upstream' lock!

Note: While holding the GLAutoDrawable locks, GLAutoDrawable.invoke(..) 
      cannot be issued, since it may be performed off-thread.
Comment 1 Sven Gothel 2014-07-27 23:26:06 CEST
c77b8f586cb2553582a42f5b90aeee5ef85f1efe

GLAutoDrawable (API CHANGE) allowing atomic operations:
    - Add class API-doc chapter about 'GLAutoDrawable Locking'

    - Add method invoke(..) API-doc description about 
      throwing IllegalStateException in case of a 
      detected deadlock situation ahead
      (Note: Implemented in GLDrawableHelper.invoke(..) for all implementations)

    - Add new methods for proper multithread handling:
    - public RecursiveLock getUpstreamLock();
    - public boolean isThreadGLCapable();

+++

GLEventListenerState/GLDrawableUtil:

    - Perform operation in a atomic fashion,
    i.e. lock GLAutoDrawable during whole operations:
        - GLDrawableUtil.swapGLContext(..)
        - GLDrawableUtil.swapGLContextAndAllGLEventListener(..)
        - GLEventListenerState.moveFrom(..)
        - GLEventListenerState.moveTo(..)

    - ReshapeGLEventListener:
    - Moved from 
        GLEventListenerState.ReshapeGLEventListener 
        ->  GLDrawableUtil.ReshapeGLEventListener
    - Takes 'displayAfterReshape' case into account.

+++

javax.media.opengl.Threading Clarifications:
    - Public 'enum Mode', i.e. Threading.Mode

    - Public getMode()

    - Clarified 'isOpenGLThread()':
    - Take 'singleThreaded' into account directly,
        i.e. always return 'true' if singleThreaded == false