HGL with GHC in Win32
Alastair Reid
reid@cs.utah.edu
21 Jun 2002 17:11:41 +0100
Thanks for looking at this Claus.
> - the full-screen titlebar effect with the SOE variant suggests
> some window-handling incompatibility, if it wasn't for Hugs and GHC
> using the same graphics source code.. (is there a difference in the
> win32 bindings for Hugs vs GHC?)
[This mail got rather long. My best guess is that yield on GHC
doesn't yield as thoroughly as on Hugs and that the Win32 library
isn't being greencarded with the --safe-code flag. (Either by itself
would probably be fine, it's having both at once that is probably
killing you.)]
I believe they're the same.
More likely is a difference in the concurrency models of Hugs and GHC.
To make the X11 code work with Hugs we had to:
1) Add a call to yield in the event loop.
lib/x11/GraphicsWindows.hs(line 360):
loop = do
-- We yield at this point because we're (potentially)
-- about to block so we should give other threads a chance
-- to run.
>>> yield
ws <- readMVar wnds
if (null ws)
then return ()
else do
handleEvent
loop
It looks as though this fix is part of the Win32 version.
(lib/win32/GraphicsWND.hs(line 124))
There is the possibility that yield does something different on GHC
than it does on Hugs. On Hugs, yield guarantees not to run this thread
until all other threads do one of:
block
terminate
yield
This guarantee is required if you're going to write
producer-consumer style threads if the producer can possibly block
waiting for input (such as Window events).
But this shouldn't be needed because of the way that GHC does
ccalls - running them in fresh threads, etc. Unless.... unless...
GHC is making 'unsafe' ccalls instead of 'safe' ones. Is GreenCard
being invoked with the --safe-code flag?
2) Fix a race condition between the code that detects when there's no
more windows to service and the code that creates windows:
lib/x11/GraphicsWindows.hs(line 142):
-- HN 2001-01-30
-- There is a race condition here since the event loop terminates if it
-- encounters an empty window list (in the global, imperative, variable
-- wnds). Thus, if m has not yet opened a window (assuming it will!)
-- when the event_loop is entered, it will exit immediately.
-- Solution: wait until either the window list is non-empty, or until
-- m exits (in case it does not open a window for some reason).
mDone <- newIORef False
forkIO (catchErrors m `finally` writeIORef mDone True)
let loop = do
yield
ws <- readMVar wnds
d <- readIORef mDone
if not (null ws) then
main_eloop display
else if not d then
loop
else
return ()
It looks as though this fix is part of the Win32 version.
(If I recall correctly, it was there from day 1)
(lib/win32/GraphicsWindows.hs(line 83))
> It seems that others started to look into this some 6 months ago,
> which is why the SOE version is slightly more successful, but no
> further progress is recorded in CVS. Has anyone succeeded in
> removing the remaining quirks?
I thought we had it working back in April 2001. I clearly remember it
running on Unix and _thought_ that we'd run it on Win32 too. I guess
I could be mistaken about the latter.
--
Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/