How does HOpenGL behave with regards to other threads and TChans in Haskell?
===

I'm doing some proof-of-concept work for a fairly complex video game I'd like to write in Haskell using the HOpenGL library. I started by writing a module that implements client-server event based communication. My problem appears when I try to hook it up to a simple program to draw clicks on the screen. 

The event library uses a list of TChans made into a priority queue for communication. It returns an "out" queue and an "in" queue corresponding to server-bound and client-bound messages. Sending and receiving events are done in separate threads using forkIO. Testing the event library without the OpenGL part shows it communicating successfully. Here's the code I used to test it:
<!-- language-all: haskell -->

    -- Client connects to server at localhost with 3 priorities in the priority queue
    do { (outQueue, inQueue) <- client Nothing 3
       -- send 'Click' events until terminated, the server responds with the coords negated
       ; mapM_ (\x -> atomically $ writeThing outQueue (lookupPriority x) x)
               (repeat (Click (fromIntegral 2) (fromIntegral 4)))
       }

This produces the expected output, namely a whole lot of send and receive events. I don't think the problem lies with the Event handling library. 

The OpenGL part of the code checks the incoming queue for new events in the displayCallback and then calls the event's associated handler. I can get one event (the Init event, which simply clears the screen) to be caught by the displayCallback, but after that nothing is caught. Here's the relevant code:

    atomically $ PQ.writeThing inqueue (Events.lookupPriority Events.Init) Events.Init
        GLUT.mainLoop

    render pqueue =
        do  event <- atomically $
                do  e <- PQ.getThing pqueue
                    case e of
                        Nothing -> retry
                        Just event -> return event
            putStrLn $ "Got event"
            (Events.lookupHandler event Events.Client) event
            GL.flush
            GLUT.swapBuffers

So my theories as to why this is happening are:

 - The display callback is blocking all of the sending and receiving threads on the retry.
 - The queues are not being returned properly, so that the queues that the client reads are different than the ones that the OpenGL part reads.

Are there any other reasons why this could be happening?

The complete code for this is too long to post on here although not too long (5 files under 100 lines each), however it is all on GitHub [here][1].

  [1]: https://github.com/RocketPuppy/PupEvents