packages feed

gi-gtk-hs 0.3.5.0 → 0.3.6.1

raw patch · 2 files changed

+144/−4 lines, 2 filesdep ~basedep ~base-compatnew-uploader

Dependency ranges changed: base, base-compat

Files

gi-gtk-hs.cabal view
@@ -1,5 +1,5 @@ name:                gi-gtk-hs-version:             0.3.5.0+version:             0.3.6.1 synopsis:            A wrapper for gi-gtk, adding a few more idiomatic API parts on top description:         A wrapper for gi-gtk, adding a few more idiomatic API parts on top homepage:            https://github.com/haskell-gi/gi-gtk-hs@@ -18,6 +18,7 @@ library   exposed-modules:     Data.GI.Gtk,                        Data.GI.Gtk.BuildFn+                       Data.GI.Gtk.Threading                        Data.GI.Gtk.ModelView.Types                        Data.GI.Gtk.ModelView.CellLayout                        Data.GI.Gtk.ModelView.CustomStore@@ -26,13 +27,13 @@                        Data.GI.Gtk.ModelView.TreeModel                        Data.GI.Gtk.ComboBox -  build-depends:       base >=4.7 && <4.11,-                       base-compat >=0.9.0 && <0.10,+  build-depends:       base >=4.7 && <5,+                       base-compat >=0.9.0 && <0.11,                        mtl >=2.1 && <2.3,                        transformers >=0.3.0.0 && <0.6,                        containers >=0.5.5.1 && <0.6,                        text >=1.2 && <1.3,-                       haskell-gi-base >=0.20 && <0.21,+                       haskell-gi-base >=0.20 && <0.22,                        gi-glib >=2.0.6 && <2.1,                        gi-gobject >=2.0.6 && <2.1,                        gi-gdk >=3.0.6 && <3.1,
+ src/Data/GI/Gtk/Threading.hs view
@@ -0,0 +1,139 @@+-- -*-haskell-*-+--+-- Author : Brandon Sloane+--+-- Created: 16 August 2017+--+-- Copyright (C) 2017 Brandon Sloane+--+--  This library is free software; you can redistribute it and/or+--  modify it under the terms of the GNU Lesser General Public+--  License as published by the Free Software Foundation; either+--  version 2.1 of the License, or (at your option) any later version.+--+--  This library is distributed in the hope that it will be useful,+--  but WITHOUT ANY WARRANTY; without even the implied warranty of+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+--  Lesser General Public License for more details.+--+-- |+-- Stability   : provisional+-- Portability : portable (depends on GHC)+--+-- Utility functions for threading+--+module Data.GI.Gtk.Threading+    (+-- | Utility functions to run IO actions on the GUI thread. You must call+-- 'Data.GI.Gtk.Threading.setGUIThread' or 'Data.GI.Gtk.Threading.setCurrentThreadAsGUIThread'+-- before using the synchronous options, or you risk deadlocking.+--+-- Note that the notion of "Thread" used by this module corresponds to operating system threads, not Haskell threads.+-- A single operating system thread may run multiple Haskell threads, and a Haskell thread may migrate between operating system threads.+-- In order for this nothing of "Thread" to make sense to a Haskell program, we must be working in a bound Haskell thread, which is tied to a single operating system thread.+-- Haskell's main function is automatically bound, and the postGUI functions will create a new bound thread if nessasary.+      setGUIThread+    , getGUIThread+    , setCurrentThreadAsGUIThread+    , postGUISyncWithPriority+    , postGUISync+    , postGUIASyncWithPriority+    , postGUIASync+    , compareThreads+    , isGUIThread+    , module GI.GLib --threadSelf and Thread+    ) where++import Control.Concurrent+import Control.Concurrent.MVar+import Data.Int (Int32)+import System.IO.Unsafe (unsafePerformIO)+import System.IO (stderr, hPutStrLn)+import GI.Gdk (threadsAddIdle)+import GI.GLib.Constants+import GI.GLib (threadSelf, Thread(..))+import Data.GI.Base.ManagedPtr+++guiThread :: MVar (Maybe Thread)+{-# NOINLINE guiThread #-}+guiThread = unsafePerformIO $ newMVar Nothing++-- | Inform gi-gtk-hs what thread is running the gtk main loop.+setGUIThread :: Thread -> IO ()+setGUIThread t = swapMVar guiThread (Just t) >> return ()++-- | Inform gi-gtk-hs that the current thread is, or will be, running the gtk main loop.+--+-- Equivalent to @'GI.GLib.threadSelf' >>= 'Data.GI.Gtk.Threading.setGUIThread'@+setCurrentThreadAsGUIThread :: IO ()+setCurrentThreadAsGUIThread = threadSelf >>= setGUIThread++-- | Get the Thread that is running the Gtk main loop, if it has been set.+getGUIThread :: IO (Maybe Thread)+getGUIThread = readMVar guiThread++-- | Queue an action to be run in the GTK event loop.+-- If called from the same process as the event loop, this runs the action directly.+-- Otherwise, this queues it in GTK's event loop and blocks until the action is complete+--+-- You must call 'Data.GI.Gtk.Threading.setGUIThread' or 'Data.GI.Gtk.Threading.setCurrentThreadAsGUIThread' before this.+--+-- Priority is typically between 'GI.GLib.Constants.PRIORITY_HIGH_IDLE' (100) and 'GI.GLib.Constants.PRIORITY_DEFAULT_IDLE' (200)+postGUISyncWithPriority :: Int32 -> IO a -> IO a+postGUISyncWithPriority priority action = runInBoundThread $ do+    b <- isGUIThread+    if b then+        action+    else+        run+    where+    run = do+        ans <- newEmptyMVar+        threadsAddIdle priority $ action >>= putMVar ans >> return False+        takeMVar ans++-- | Queue an action to be run in the GTK event loop.+-- If called from the same process as the event loop, this runs the action directly.+-- Otherwise, this queues it in GTK's event loop and blocks until the action is complete+--+-- You must call 'Data.GI.Gtk.Threading.setGUIThread' or 'Data.GI.Gtk.Threading.setCurrentThreadAsGUIThread' before this.+--+-- Equivalent to @'Data.GI.Gtk.Threading.postGUISyncWithPriority' 'GI.GLib.Constants.PRIORITY_DEFAULT_IDLE'@+postGUISync :: IO a -> IO a+postGUISync = postGUISyncWithPriority PRIORITY_DEFAULT_IDLE++-- | Queue an action to be run in the GTK event loop.+-- This function queues the event regardless of what process it is called from, and returns immidietly.+--+-- Priority is typically between 'GI.GLib.Constants.PRIORITY_HIGH_IDLE' (100) and 'GI.GLib.Constants.PRIORITY_DEFAULT_IDLE' (200)+postGUIASyncWithPriority :: Int32 -> IO () -> IO ()+postGUIASyncWithPriority priority action = threadsAddIdle priority (action >> return False) >> return ()++-- | Queue an action to be run in the GTK event loop.+-- This function queues the event regardless of what process it is called from, and returns immidietly.+--+-- Equivalent to @'Data.GI.Gtk.Threading.postGUIASyncWithPriority' 'GI.GLib.Constants.PRIORITY_DEFAULT_IDLE'@+postGUIASync :: IO () -> IO ()+postGUIASync = postGUIASyncWithPriority PRIORITY_DEFAULT_IDLE++-- | Test if two 'GI.GLib.Structs.Thread.Thread's refer to the same OS thread.+-- A 'GI.GLib.Structs.Thread.Thread' can be gotten from 'GI.GLib.Structs.Thread.threadSelf'.+-- Note that 'GI.GLib.Structs.Thread.threadSelf' only makes sense from a bound thread.+compareThreads :: Thread -> Thread -> IO Bool+compareThreads (Thread mptr1) (Thread mptr2) =+    withManagedPtr mptr1 $ \ptr1 ->+    withManagedPtr mptr2 $ \ptr2 ->+    return $ ptr1 == ptr2++-- | Check if the current thread is the Gtk gui thread.+--+-- You must call 'Data.GI.Gtk.Threading.setGUIThread' or 'Data.GI.Gtk.Threading.setCurrentThreadAsGUIThread' before this.+-- This only makes sense when called from a bound thread.+isGUIThread :: IO Bool+isGUIThread = do+    guiThread <- getGUIThread+    case guiThread of+        Nothing -> hPutStrLn stderr "WARNING Data.GI.Gtk.Threading Calling isGUIThread before setGUIThread" >> return False+        Just t1 -> threadSelf >>= compareThreads t1+