From: Andy S. <laz...@gm...> - 2010-05-28 15:29:34
|
Christian Maeder <Chr...@df...> writes: > Andy Stewart schrieb: >> Oh, looks like is new issue. >> >> I think you need a minimum program make other people can recure >> this bug. > > Right, that's a problem. > >>> I suppose I should try out some gtk demo programs. Do I need to darcs >>> get them? >> Yes, because we forgot add demo in gtk2hs-0.11.0 >> So you need get deom from darcs. > > All demos work under x86_solaris (ghc-6.10.4)! (only graphic/Drawing.hs > could not be compiled) Because we change some GDK APIs. > > We start with startMainLoop: > > startMainLoop :: IO () > startMainLoop = forkIO_ $ do > unsafeInitGUIForThreadedRTS > mainGUI > > forkIO_ :: IO () -> IO () > forkIO_ f = forkIO f >> return () > > Is this already a problem? First, if you use unsafeInitGUIForThreadedRTS, you need enable "-thread" flag. I guess you want running concurrent threads in gtk2hs program, right? Generally, we hook `forkIO` in user's event, and not use forkIO wrap mainGUI (of course, you can use `forever` wrap your startMainLoop). When we use unsafeInitGUIForThreadedRTS, we can running different code in different threads, but when we call GTK+ code in thread, we must use `postGUIAsync` wrap your GTK+ code that make all GTK+ code post to GTK+ main thread, render same widget in two threads is wrong! The purpose of concurrent GTK+ program is, don't block user's input when we do long-time calculation. So i create "forkGuiIO_ :: IO a -> (a -> IO ()) -> IO ()", the design of forkGuiIO_ is split "long-time background action" and "GTK+ render action". In forkGuiIO_ define, "IO a" is long-time calculation that don't include any gtk+ code "(a -> IO ())" is gtk+ code to render in GTK+ main thread. (a -> IO ()) will render widget in GTK+ main thread when it catch "finish signal" from "IO a" Detail code looks below: ------------------------------> demo start <------------------------------ main :: IO () main = do unsafeInitGUIForThreadedRTS window <- windowNew window `onDestroy` mainQuit window `on` keyPressEvent $ tryEvent $ do liftIO (forkGuiIO_ longTimeAction guiRenderAction) widgetShowAll window mainGUI -- | Fork GUI IO. forkGuiIO :: IO a -> (a -> IO ()) -> IO (MVar a, ThreadId, ThreadId) forkGuiIO calcAction guiAction = do -- Create signal MVar variable. signal <- newEmptyMVar -- Build new thread for long-time calculation. calcThreadId <- forkIO $ calcAction >>= putMVar signal -- fill signal when calculation finish -- Bulid new thread for listen signal. guiThreadId <- onGuiSignal signal guiAction -- post GUI action to Gtk+ thread when catch finish signal return (signal, calcThreadId, guiThreadId) -- | Simliar `forkGuiIO`, except return () forkGuiIO_ :: IO a -> (a -> IO ()) -> IO () forkGuiIO_ calcAction guiAction = forkGuiIO calcAction guiAction >> return () -- | Post GUI Action to Gtk+ thread when catch signal. onGuiSignal :: MVar a -> (a -> IO ()) -> IO ThreadId onGuiSignal signal guiAction = forkIO $ takeMVar signal >>= postGUIAsync . guiAction ------------------------------> demo end <------------------------------ Hope above will help you. Cheers, -- Andy |