src/Tools/Haskell/Haskell.thy
changeset 69499 638fdbbc7d1f
parent 69498 22e958b76bf6
child 69628 a2fbfdc5e62d
equal deleted inserted replaced
69498:22e958b76bf6 69499:638fdbbc7d1f
  1689 
  1689 
  1690 module Isabelle.Standard_Thread (
  1690 module Isabelle.Standard_Thread (
  1691   ThreadId, Result,
  1691   ThreadId, Result,
  1692   find_id,
  1692   find_id,
  1693   properties, change_properties,
  1693   properties, change_properties,
       
  1694   add_resource, del_resource, bracket_resource,
  1694   is_stopped, expose_stopped, stop,
  1695   is_stopped, expose_stopped, stop,
  1695   my_uuid, stop_uuid,
  1696   my_uuid, stop_uuid,
  1696   Fork, fork_finally, fork)
  1697   Fork, fork_finally, fork)
  1697 where
  1698 where
  1698 
  1699 
       
  1700 import Data.Unique
  1699 import Data.Maybe
  1701 import Data.Maybe
  1700 import Data.IORef
  1702 import Data.IORef
  1701 import System.IO.Unsafe
  1703 import System.IO.Unsafe
  1702 
  1704 
  1703 import qualified Data.List as List
  1705 import qualified Data.List as List
  1714 import qualified Isabelle.Properties as Properties
  1716 import qualified Isabelle.Properties as Properties
  1715 
  1717 
  1716 
  1718 
  1717 {- thread info -}
  1719 {- thread info -}
  1718 
  1720 
  1719 data Info = Info {uuid :: UUID.T, props :: Properties.T, stopped :: Bool}
  1721 type Resources = Map Unique (IO ())
       
  1722 data Info = Info {uuid :: UUID.T, props :: Properties.T, stopped :: Bool, resources :: Resources}
  1720 type Infos = Map ThreadId Info
  1723 type Infos = Map ThreadId Info
  1721 
  1724 
  1722 lookup_info :: Infos -> ThreadId -> Maybe Info
  1725 lookup_info :: Infos -> ThreadId -> Maybe Info
  1723 lookup_info infos id = Map.lookup id infos
  1726 lookup_info infos id = Map.lookup id infos
  1724 
  1727 
  1725 init_info :: ThreadId -> UUID.T -> Infos -> (Infos, ())
  1728 init_info :: ThreadId -> UUID.T -> Infos -> (Infos, ())
  1726 init_info id uuid infos = (Map.insert id (Info uuid [] False) infos, ())
  1729 init_info id uuid infos = (Map.insert id (Info uuid [] False Map.empty) infos, ())
  1727 
  1730 
  1728 
  1731 
  1729 {- global state -}
  1732 {- global state -}
  1730 
  1733 
  1731 {-# NOINLINE global_state #-}
  1734 {-# NOINLINE global_state #-}
  1740 get_info :: ThreadId -> IO (Maybe Info)
  1743 get_info :: ThreadId -> IO (Maybe Info)
  1741 get_info id = do
  1744 get_info id = do
  1742   state <- readIORef global_state
  1745   state <- readIORef global_state
  1743   return $ lookup_info state id
  1746   return $ lookup_info state id
  1744 
  1747 
  1745 map_info :: ThreadId -> (Info -> Info) -> IO ()
  1748 map_info :: ThreadId -> (Info -> Info) -> IO (Maybe Info)
  1746 map_info id f =
  1749 map_info id f =
  1747   atomicModifyIORef' global_state
  1750   atomicModifyIORef' global_state
  1748     (\infos ->
  1751     (\infos ->
  1749       case lookup_info infos id of
  1752       case lookup_info infos id of
  1750         Nothing -> (infos, ())
  1753         Nothing -> (infos, Nothing)
  1751         Just info -> (Map.insert id (f info) infos, ()))
  1754         Just info ->
       
  1755           let info' = f info
       
  1756           in (Map.insert id info' infos, Just info'))
  1752 
  1757 
  1753 delete_info :: ThreadId -> IO ()
  1758 delete_info :: ThreadId -> IO ()
  1754 delete_info id =
  1759 delete_info id =
  1755   atomicModifyIORef' global_state (\infos -> (Map.delete id infos, ()))
  1760   atomicModifyIORef' global_state (\infos -> (Map.delete id infos, ()))
  1756 
  1761 
  1767 
  1772 
  1768 change_properties :: (Properties.T -> Properties.T) -> IO ()
  1773 change_properties :: (Properties.T -> Properties.T) -> IO ()
  1769 change_properties f = do
  1774 change_properties f = do
  1770   id <- Concurrent.myThreadId
  1775   id <- Concurrent.myThreadId
  1771   map_info id (\info -> info {props = f (props info)})
  1776   map_info id (\info -> info {props = f (props info)})
       
  1777   return ()
       
  1778 
       
  1779 
       
  1780 {- managed resources -}
       
  1781 
       
  1782 add_resource :: IO () -> IO Unique
       
  1783 add_resource resource = do
       
  1784   id <- Concurrent.myThreadId
       
  1785   u <- newUnique
       
  1786   map_info id (\info -> info {resources = Map.insert u resource (resources info)})
       
  1787   return u
       
  1788 
       
  1789 del_resource :: Unique -> IO ()
       
  1790 del_resource u = do
       
  1791   id <- Concurrent.myThreadId
       
  1792   map_info id (\info -> info {resources = Map.delete u (resources info)})
       
  1793   return ()
       
  1794 
       
  1795 bracket_resource :: IO () -> IO a -> IO a
       
  1796 bracket_resource resource body =
       
  1797   Exception.bracket (add_resource resource) del_resource (const body)
  1772 
  1798 
  1773 
  1799 
  1774 {- stop -}
  1800 {- stop -}
  1775 
  1801 
  1776 is_stopped :: IO Bool
  1802 is_stopped :: IO Bool
  1780 expose_stopped = do
  1806 expose_stopped = do
  1781   stopped <- is_stopped
  1807   stopped <- is_stopped
  1782   when stopped $ throw ThreadKilled
  1808   when stopped $ throw ThreadKilled
  1783 
  1809 
  1784 stop :: ThreadId -> IO ()
  1810 stop :: ThreadId -> IO ()
  1785 stop id = map_info id (\info -> info {stopped = True})
  1811 stop id = do
       
  1812   info <- map_info id (\info -> info {stopped = True})
       
  1813   let ops = case info of Nothing -> []; Just Info{resources} -> map snd (Map.toDescList resources)
       
  1814   sequence_ ops
  1786 
  1815 
  1787 
  1816 
  1788 {- UUID -}
  1817 {- UUID -}
  1789 
  1818 
  1790 my_uuid :: IO (Maybe UUID.T)
  1819 my_uuid :: IO (Maybe UUID.T)