Tackling IO (the correct way)

Hi again all, I could do with some design pointers for a project I'm working on combining Haskell with a robot. My situation is: I read sensor data from the robot lazily a line at a time, as soon as a line is read in my code sends out a response down a pipe. Implemented in this fashion:
mapM_ (updateFunction myIORef) fromRobot ::IO () fromRobot :: String updateFunction :: IORef -> String -> IO ()
Now I wish to update a HOpenGL window synchronously with this. To establish this I make a new HOpenGL window & return an IORef (IO ()) which holds the actions to draw my graphics. In this fashion:
myIORef <- makeWindow --- Above code --- mainLoop
This can be passed to updateFunction as shown above so every time it processes a new line from the robot is can update the graphics via the IORef. Because neither 'mapM_ (updateFunction myIORef) fromRobot' nor 'mainLoop' terminate I've been using 'forkIO' to split one off. This way the lazy evaluation keeps running and then window keeps updating itself. This works, sort of. I have problems because the my HOpenGL code also has magic to allow you to change the point of view using the keyboard. But when I do I get this after a while: LOCK SET! Previous intel_span.c:210 Current: intel_batchbuffer.c:63 Can anyone suggest how to resolve this "two functions which never terminate but both share IORefs" problem? Many thanks, Dave

On Thu, Aug 23, 2007 at 06:04:54AM +0100, Dave Tapley wrote: ...
Now I wish to update a HOpenGL window synchronously with this. To establish this I make a new HOpenGL window & return an IORef (IO ()) which holds the actions to draw my graphics. In this fashion: ... Because neither 'mapM_ (updateFunction myIORef) fromRobot' nor 'mainLoop' terminate I've been using 'forkIO' to split one off. This way the lazy evaluation keeps running and then window keeps updating itself. ... This works, sort of. I have problems because the my HOpenGL code also has magic to allow you to change the point of view using the keyboard. But when I do I get this after a while:
LOCK SET! Previous intel_span.c:210 Current: intel_batchbuffer.c:63
Can anyone suggest how to resolve this "two functions which never terminate but both share IORefs" problem?
I don't know if this is your problem, but calling OpenGL from a thread created using forkIO is an extremely bad idea. forkIO does not guarantee a one-to-one mapping between Haskell threads and OS threads used for foreign calls, which horribly breaks broken APIs like OpenGL that use thread local state. Use forkOS instead for things like this. Stefan

Dave Tapley wrote:
Hi again all, I could do with some design pointers for a project I'm working on combining Haskell with a robot.
My situation is:
I read sensor data from the robot lazily a line at a time, as soon as a line is read in my code sends out a response down a pipe. Implemented in this fashion:
mapM_ (updateFunction myIORef) fromRobot ::IO () fromRobot :: String updateFunction :: IORef -> String -> IO ()
Now I wish to update a HOpenGL window synchronously with this. To establish this I make a new HOpenGL window & return an IORef (IO ()) which holds the actions to draw my graphics. In this fashion:
myIORef <- makeWindow --- Above code --- mainLoop
This can be passed to updateFunction as shown above so every time it processes a new line from the robot is can update the graphics via the IORef.
Because neither 'mapM_ (updateFunction myIORef) fromRobot' nor 'mainLoop' terminate I've been using 'forkIO' to split one off. This way the lazy evaluation keeps running and then window keeps updating itself.
This works, sort of. I have problems because the my HOpenGL code also has magic to allow you to change the point of view using the keyboard. But when I do I get this after a while:
LOCK SET! Previous intel_span.c:210 Current: intel_batchbuffer.c:63
Can anyone suggest how to resolve this "two functions which never terminate but both share IORefs" problem?
Using IORefs in two different threads probably needs MVars [1] or TVars (atomically :: STM a -> IO a) [2] instead, to do it safely, which are both similar to IORefs (choose whichever interface fits your usage better, I guess). (And using forkOS like Stefan says) [1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurren... [2] no documentation where it should be: http://www.haskell.org/ghc/docs/latest/html/libraries/stm/Control-Concurrent... but some documentation here: http://www.haskell.org/ghc/docs/latest/html/libraries/base/GHC-Conc.html#t%3... Isaac

Hello Isaac, Thursday, August 23, 2007, 4:17:52 PM, you wrote:
Using IORefs in two different threads probably needs MVars [1] or TVars
no documentation where it should be:
the best documentation still is "Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell" http://research.microsoft.com/Users/simonpj/papers/marktoberdorf/marktoberdo... -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (4)
-
Bulat Ziganshin
-
Dave Tapley
-
Isaac Dupree
-
Stefan O'Rear