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

   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:


   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
      ws <- readMVar wnds      
      d  <- readIORef mDone
      if not (null ws) then
          main_eloop display
       else if not d then
	  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/