|
ford.304
|
 |
« Reply #30 on: 02. October 2009, 07:02:31 pm » |
|
So I have at least figured out what causes deadlock if I try to synchronize the canvas refresh on the render lock.
In the render thread, the RenderLock is first acquired at DefaultRenderer.renderOnce() at line 535. A lock to the GLJPanel is acquired at CanvasPeerImplSwing.initRenderingImpl(): 644 at the glJPanel.display() call.
However, in the AWT-EventQueue thread, this lock is already held from the GLJPanel.paintComponent() call. Unfortunately, this happens long before the drawing call is passed into xith and we can try to lock at CanvasPeerImplBase.display:619, which is why the synchronized call there is commented out.
So, it seems to me we have two immediately presented options - either reverse the ordering of the locks and manually synchronize on GLJPanel before locking on the renderLock, or removing the renderLock entirely and locking only on the GLJPanel. I'll admit to not knowing the threading in xith well enough to be sure, but I would lean toward locking on the GLJPanel directly. However, I can see some issues with that, so I'm interested in your take on this.
There needs to be a shared lock around the rendering methods used by the Canvas3DJPanel and the RenderLoop if we keep the same refresh paradigm for the JPanel, the only question is how to put it there.
|
|
|
|
|
Logged
|
|
|
|
Marvin Fröhlich
Xith Lord
Administrator
Guru
   
Offline
Posts: 4381
May the 4th, be with you...
|
 |
« Reply #31 on: 02. October 2009, 10:54:37 pm » |
|
CanvasPeerImplAWT synchronizes to getRenderLock() as well as DefaultRenderer.
Marvin
|
|
|
|
|
Logged
|
|
|
|
|
ford.304
|
 |
« Reply #32 on: 05. October 2009, 12:54:51 pm » |
|
Well, yes, if but CanvasPeerImplSwing synchronizes to getRenderLock(), you have deadlock. Do you know what lock the swing call to display() has? It is being grabbed by both the GLPanel.display method and the swing repaint messages that are calling CanvasPeerImplSwing.display().
As I said, I tried substituting an AWT canvas and when it is placed into our Swing GUI I get an exception.
I feel pretty confident as to the cause of this deadlock, I'm just having a time finding a solution to get the locks in the right order.
|
|
|
|
|
Logged
|
|
|
|
Marvin Fröhlich
Xith Lord
Administrator
Guru
   
Offline
Posts: 4381
May the 4th, be with you...
|
 |
« Reply #33 on: 05. October 2009, 02:10:22 pm » |
|
I'm sorry. I remember, I tried to find a good locking for these canvases, but didn't find it. So I commented it out and it worked for me. Apparently it doesn't actually work. But I don't have an idea, what the right lock would have to be without investigating it, for which I don't have tie atm.
Marvin
|
|
|
|
|
Logged
|
|
|
|
|
ford.304
|
 |
« Reply #34 on: 05. October 2009, 03:19:01 pm » |
|
It's cool, I understand time problems. I'm still working through it.
I *think* the lock is actually the EventQueue lock, which... I don't think you can get access to.
I looked at the JOGL code, and the GLJPanel doesn't actually draw anything when you call it from outside of the AWT event thread, it just registers a display event with the AWT event queue. And that's the call that it's deadlocking on.
Soo... I either need to find a way to move that call (and probably any other GLJPanel calls) outside of the RenderLock, or I need to rewrite the render "loop" to render in the AWT thread as a callback instead of in its own thread.
I will definitely try to send whatever fix I manage to you, since this is theoretically an issue with the swing panel in general, it just doesn't show up very often under normal operating conditions.
|
|
|
|
|
Logged
|
|
|
|
Marvin Fröhlich
Xith Lord
Administrator
Guru
   
Offline
Posts: 4381
May the 4th, be with you...
|
 |
« Reply #35 on: 05. October 2009, 04:14:04 pm » |
|
Just an idea: IIRC, there is a way to invoke the render call in JOGL like in LWJGL, i.e. you do all the thread handling on your own, but don't let it be handled by the callback mechanism. Maybe we can use that to circumvent JOGL's crazy threading.
Marvin
|
|
|
|
|
Logged
|
|
|
|
|
ford.304
|
 |
« Reply #36 on: 05. October 2009, 06:25:28 pm » |
|
So I found *a* solution. You may want to rearrange it a little bit to match your abstractions/naming conventions.
The issue/solution is twofold:
1) Synchronize on the renderLock in the CanvasPeerImplSwing.display() method. 2) Move the GLJPanel.display() method in CanvasPeerImplSwing.initRenderingImpl outside of the renderlock.
As a quick hack to get it working, I added a "finish()" method to the CanvasPeer interface that does nothing in all implementations but the swing one. In the Swing implementation, it calls glJPanel.display(). I then deleted the existing call to glJPanel.display in initRenderingImpl. I added a call to my finish method immediately following the synchronized code in DefaultRenderer.renderOnceInternal(). This makes sure that the display refresh is still called, but it occurs outside of the render lock, so there is no deadlock.
So far with my testing this seeems to resolve the issue. The interface is a little bit hackish, though. I'm not sure how you want to arrange it to make it cleaner. All that matters is that the CanvasPeerImplSwing.display method *does* have a renderlock, and that any glJPanel.display call happens outside of that lock.
Does that make sense?
How do you prefer suggested patches be submitted? Email?
|
|
|
|
|
Logged
|
|
|
|
Marvin Fröhlich
Xith Lord
Administrator
Guru
   
Offline
Posts: 4381
May the 4th, be with you...
|
 |
« Reply #37 on: 06. October 2009, 01:19:24 am » |
|
Sounds like a good solution. Please commit it to SVN. This is the easiest way to commit and to compare it.
Marvin
|
|
|
|
|
Logged
|
|
|
|
|