From: Duncan C. <dun...@wo...> - 2007-07-04 15:35:43
|
Tue Jul 3 18:24:35 PDT 2007 Duncan Coutts <du...@ha...> * Reimplement the way we keep track of gthread initialisation state Sadly we cannot just call g_thread_supported() because this macro expands into a reference to a gloabl variable that lives in the gthread dynamic lib. On windows, GHCi's dynamic linker cannot cope with references to global vars from C dlls. So instead we keep a global var in the wrapper, so it's in the same package, rather than crossing a dll boundary. This allows us to track the state, and because the state is allocated in C land, it survives :reload in GHCi, which was the problem with the original scheme. Ugg. hunk ./gtk/Graphics/UI/Gtk/General/General.chs 163 -initialiseGThreads :: IO () -initialiseGThreads = do - gthreadsInitialised <- liftM (toBool . fromIntegral) gtk2hs_thread_supported - when (not gthreadsInitialised) $ do - {# call unsafe g_thread_init #} nullPtr - -foreign import ccall "hsgthread.h gtk2hs_thread_supported" - gtk2hs_thread_supported :: IO CInt +foreign import ccall "hsgthread.h gtk2hs_threads_initialise" + initialiseGThreads :: IO () hunk ./gtk/Graphics/UI/Gtk/General/hsgthread.c 1 -/* Annoyingly, g_thread_supported is actuall a macro so we need this silly - * little wrapper functions. Grrr. */ +/* We would use the g_thread_supported macro here, but unfortunately on + * windows GHCi's dynamic linker cannot cope with references to global + * variables imported from dlls. + * + * So instead of asking glib if we (or indeed) anyone else has initialised + * the glib gthread system, we keep track of it ourselves. We still have to + * do it in C land so the state survives :reload in GHCi. So there is the + * danger in a mixed language program, of someone else initialising the + * glib thread system and us not being aware of it. :-( + */ hunk ./gtk/Graphics/UI/Gtk/General/hsgthread.c 14 -int gtk2hs_thread_supported () { - return g_thread_supported(); +void gtk2hs_threads_initialise () { + static int threads_initialised = 0; + + if (!threads_initialised) { + threads_initialised = 1; + g_thread_init(NULL); + } hunk ./gtk/Graphics/UI/Gtk/General/hsgthread.h 1 -/* g_thread_supported wrapper function */ - -int gtk2hs_thread_supported (); +int gtk2hs_threads_initialise (); |