
This is nasty. As I understand it, * GLUT assumes that the same OS thread executes some Haskell code, calls C, which calls back to Haskell. * Concurrent Haskell never lets this happen, for very good reason. The thread executing Haskell code is just an anonymous OS thread executing multiple Haskell threads. The good reason is this: if one designated OS thread must execute a particular bunch of Haskell code, what if that OS thread gets blocked doing I/O on behalf of some other Haskell thread? It's hard to say just which Haskell threads "belong" to that designated OS thread. The only thing I can think of is that the Haskell call-back thread somehow says that it can only be executed by the designated OS thread; and when blocks (the Haskell call-back, that is) the OS thread doesn't grab another Haskell thread to execute, but instead steps aside for an anonymous worker thread to do the job. Makes it all more complicated, alas. Is there no way to get the "current context" explicitly, and treat it as some kind of "handle" that accompanies GLUT calls? I counsel caution here. It's easy to hack something up that will puzzle us for generations. Check out Sigbjorn's notes in the GHC commentary. Whatever we end up doing should be documented there. Simon | -----Original Message----- | From: Wolfgang Thaller [mailto:wolfgang.thaller@gmx.net] | Sent: 16 June 2002 20:57 | To: hopengl@haskell.org | Cc: GHC List | Subject: HOpenGL and --enable-threaded-rts | | | In short, it doesn't work :-( . | OpenGL (at least on MacOS) keeps track of the "current context" on a | per-thread basis. The GLUT library sets the current context and calls | back to the program. With GHC 5.03 compiled with | --enable-threaded-rts, | the callback gets executed in a different thread. There is no OpenGL | context set up for that thread, so the first OpenGL call | crashes. This might also be a problem for other state-based | interfaces that use | thread-local state. | | Has anyone already thought about how to solve this problem? | I'm thinking about adding hooks to the RTS (in grabCapability, | releaseCapability and scheduleThread_) which would be used | for setting | up the correct thread-local state whenever Haskell execution | "switches" | to a different OS thread. Those hook routines would have to | be written | in C and would be platform-specific most of the time. It's not a nice | solution, but it's the only one I can think of at this time. | Unless someone comes up with a better idea _quickly_, I'll try it out | and then report how ugly it really is... :-) | | Cheers, | | Wolfgang | | _______________________________________________ | Glasgow-haskell-users mailing list | Glasgow-haskell-users@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-| haskell-users |

Simon Peyton-Jones wrote:
[...] Is there no way to get the "current context" explicitly, and treat it as some kind of "handle" that accompanies GLUT calls?
I fear this is no solution to a general problem: Most APIs out there will probably break miserably if their callbacks are executed by a thread different from the one doing the registration and/or initialization of the API. Not nice, but thread-safe APIs are not very common. :-( I don't have a good solution at hand, perhaps we could extend 'foreign import "wrapper"' by an annotation "execute callbacks in the same thread as the current one"? Ugly... Cheers, S.

Simon Peyton-Jones wrote:
This is nasty. As I understand it,
* GLUT assumes that the same OS thread executes some Haskell code, calls C, which calls back to Haskell.
All OpenGL calls operate upon the current context and window, which are per-thread settings. The context is set with glXMakeCurrent (X11) or wglMakeCurrent (Windows); this sets a specific context and a specific Drawable (X11) or DC (Windows) as current for the calling thread. IOW, the OpenGL API isn't so much thread-safe as thread-aware. This is fine if the program is managing the threads itself, but it's likely to be a nuisance within a system which switches threads arbitrarily. GLUT sets the current context/window at appropriate points (glutCreateWindow, glutSetWindow, and before invoking callbacks). This works fine providing that the OpenGL calls are made within the thread in which the callback is invoked.
* Concurrent Haskell never lets this happen, for very good reason. The thread executing Haskell code is just an anonymous OS thread executing multiple Haskell threads.
The good reason is this: if one designated OS thread must execute a particular bunch of Haskell code, what if that OS thread gets blocked doing I/O on behalf of some other Haskell thread? It's hard to say just which Haskell threads "belong" to that designated OS thread.
The only thing I can think of is that the Haskell call-back thread somehow says that it can only be executed by the designated OS thread; and when blocks (the Haskell call-back, that is) the OS thread doesn't grab another Haskell thread to execute, but instead steps aside for an anonymous worker thread to do the job. Makes it all more complicated, alas.
Is there no way to get the "current context" explicitly, and treat it as some kind of "handle" that accompanies GLUT calls?
GLUT creates its own contexts, but these aren't available to the
application; at least, not officially; the relevant variables (e.g
__glutCurrentWindow), aren't "static", so you could get them if you
really wanted.
Even so, you would still have to ensure that {glX,wgl}MakeCurrent was
called at the appropriate points. AFAICT, this would require either
interacting directly with the (OS) thread management code, or calling
{glX,wgl}MakeCurrent multiple times before *every* OpenGL call.
Basically, GLUT isn't so much a library as a complete (albeit very
simple) framework. It makes it easy to write simple OpenGL programs,
but it also makes it hard to write real programs.
OTOH, if you don't want to use GLUT, you have to interact with the
native window system, and use the platform-specific "glue" layer
(glX*, wgl* etc) to initialise and manage the rendering "environment"
(although particular toolkits may handle the latter part for you, e.g.
via an "OpenGL canvas" widget).
--
Glynn Clements
participants (3)
-
Glynn Clements
-
Simon Peyton-Jones
-
Sven Panne