equal
deleted
inserted
replaced
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) |