Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > f9b127c02f56e71454a7233185e51eb4 > files > 828

ghc-base-devel-4.3.1.0-16.fc15.i686.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ -->
<title>GHC/Conc/Sync.lhs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
\begin{code}
<pre><a name="line-1"></a><span class='hs-comment'>{-# OPTIONS_GHC -XNoImplicitPrelude #-}</span>
<a name="line-2"></a><span class='hs-comment'>{-# OPTIONS_GHC -fno-warn-missing-signatures #-}</span>
<a name="line-3"></a><span class='hs-comment'>{-# OPTIONS_HADDOCK not-home #-}</span>
<a name="line-4"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span>
<a name="line-5"></a><span class='hs-comment'>-- |</span>
<a name="line-6"></a><span class='hs-comment'>-- Module      :  GHC.Conc.Sync</span>
<a name="line-7"></a><span class='hs-comment'>-- Copyright   :  (c) The University of Glasgow, 1994-2002</span>
<a name="line-8"></a><span class='hs-comment'>-- License     :  see libraries/base/LICENSE</span>
<a name="line-9"></a><span class='hs-comment'>--</span>
<a name="line-10"></a><span class='hs-comment'>-- Maintainer  :  cvs-ghc@haskell.org</span>
<a name="line-11"></a><span class='hs-comment'>-- Stability   :  internal</span>
<a name="line-12"></a><span class='hs-comment'>-- Portability :  non-portable (GHC extensions)</span>
<a name="line-13"></a><span class='hs-comment'>--</span>
<a name="line-14"></a><span class='hs-comment'>-- Basic concurrency stuff.</span>
<a name="line-15"></a><span class='hs-comment'>--</span>
<a name="line-16"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span>
<a name="line-17"></a>
<a name="line-18"></a><span class='hs-comment'>-- No: #hide, because bits of this module are exposed by the stm package.</span>
<a name="line-19"></a><span class='hs-comment'>-- However, we don't want this module to be the home location for the</span>
<a name="line-20"></a><span class='hs-comment'>-- bits it exports, we'd rather have Control.Concurrent and the other</span>
<a name="line-21"></a><span class='hs-comment'>-- higher level modules be the home.  Hence:</span>
<a name="line-22"></a>
<a name="line-23"></a><span class='hs-cpp'>#include "Typeable.h"</span>
<a name="line-24"></a>
<a name="line-25"></a><span class='hs-comment'>-- #not-home</span>
<a name="line-26"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Conc</span><span class='hs-varop'>.</span><span class='hs-conid'>Sync</span>
<a name="line-27"></a>        <span class='hs-layout'>(</span> <span class='hs-conid'>ThreadId</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
<a name="line-28"></a>
<a name="line-29"></a>        <span class='hs-comment'>-- * Forking and suchlike</span>
<a name="line-30"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>forkIO</span>        <span class='hs-comment'>-- :: IO a -&gt; IO ThreadId</span>
<a name="line-31"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>forkIOUnmasked</span>
<a name="line-32"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>forkOnIO</span>      <span class='hs-comment'>-- :: Int -&gt; IO a -&gt; IO ThreadId</span>
<a name="line-33"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>forkOnIOUnmasked</span>
<a name="line-34"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>numCapabilities</span> <span class='hs-comment'>-- :: Int</span>
<a name="line-35"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>numSparks</span>      <span class='hs-comment'>-- :: IO Int</span>
<a name="line-36"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>childHandler</span>  <span class='hs-comment'>-- :: Exception -&gt; IO ()</span>
<a name="line-37"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>myThreadId</span>    <span class='hs-comment'>-- :: IO ThreadId</span>
<a name="line-38"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>killThread</span>    <span class='hs-comment'>-- :: ThreadId -&gt; IO ()</span>
<a name="line-39"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>throwTo</span>       <span class='hs-comment'>-- :: ThreadId -&gt; Exception -&gt; IO ()</span>
<a name="line-40"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>par</span>           <span class='hs-comment'>-- :: a -&gt; b -&gt; b</span>
<a name="line-41"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>pseq</span>          <span class='hs-comment'>-- :: a -&gt; b -&gt; b</span>
<a name="line-42"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>runSparks</span>
<a name="line-43"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>yield</span>         <span class='hs-comment'>-- :: IO ()</span>
<a name="line-44"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>labelThread</span>   <span class='hs-comment'>-- :: ThreadId -&gt; String -&gt; IO ()</span>
<a name="line-45"></a>
<a name="line-46"></a>        <span class='hs-layout'>,</span> <span class='hs-conid'>ThreadStatus</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-conid'>BlockReason</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
<a name="line-47"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>threadStatus</span>  <span class='hs-comment'>-- :: ThreadId -&gt; IO ThreadStatus</span>
<a name="line-48"></a>
<a name="line-49"></a>        <span class='hs-comment'>-- * TVars</span>
<a name="line-50"></a>        <span class='hs-layout'>,</span> <span class='hs-conid'>STM</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
<a name="line-51"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>atomically</span>    <span class='hs-comment'>-- :: STM a -&gt; IO a</span>
<a name="line-52"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>retry</span>         <span class='hs-comment'>-- :: STM a</span>
<a name="line-53"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>orElse</span>        <span class='hs-comment'>-- :: STM a -&gt; STM a -&gt; STM a</span>
<a name="line-54"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>throwSTM</span>      <span class='hs-comment'>-- :: Exception e =&gt; e -&gt; STM a</span>
<a name="line-55"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>catchSTM</span>      <span class='hs-comment'>-- :: Exception e =&gt; STM a -&gt; (e -&gt; STM a) -&gt; STM a</span>
<a name="line-56"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>alwaysSucceeds</span> <span class='hs-comment'>-- :: STM a -&gt; STM ()</span>
<a name="line-57"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>always</span>        <span class='hs-comment'>-- :: STM Bool -&gt; STM ()</span>
<a name="line-58"></a>        <span class='hs-layout'>,</span> <span class='hs-conid'>TVar</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
<a name="line-59"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>newTVar</span>       <span class='hs-comment'>-- :: a -&gt; STM (TVar a)</span>
<a name="line-60"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>newTVarIO</span>     <span class='hs-comment'>-- :: a -&gt; STM (TVar a)</span>
<a name="line-61"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>readTVar</span>      <span class='hs-comment'>-- :: TVar a -&gt; STM a</span>
<a name="line-62"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>readTVarIO</span>    <span class='hs-comment'>-- :: TVar a -&gt; IO a</span>
<a name="line-63"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>writeTVar</span>     <span class='hs-comment'>-- :: a -&gt; TVar a -&gt; STM ()</span>
<a name="line-64"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>unsafeIOToSTM</span> <span class='hs-comment'>-- :: IO a -&gt; STM a</span>
<a name="line-65"></a>
<a name="line-66"></a>        <span class='hs-comment'>-- * Miscellaneous</span>
<a name="line-67"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>withMVar</span>
<a name="line-68"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>modifyMVar_</span>
<a name="line-69"></a>
<a name="line-70"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>setUncaughtExceptionHandler</span>      <span class='hs-comment'>-- :: (Exception -&gt; IO ()) -&gt; IO ()</span>
<a name="line-71"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>getUncaughtExceptionHandler</span>      <span class='hs-comment'>-- :: IO (Exception -&gt; IO ())</span>
<a name="line-72"></a>
<a name="line-73"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>reportError</span><span class='hs-layout'>,</span> <span class='hs-varid'>reportStackOverflow</span>
<a name="line-74"></a>
<a name="line-75"></a>        <span class='hs-layout'>,</span> <span class='hs-varid'>sharedCAF</span>
<a name="line-76"></a>        <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-77"></a>
<a name="line-78"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span> <span class='hs-varid'>hiding</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafePerformIO</span><span class='hs-layout'>)</span>
<a name="line-79"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>C</span>
<a name="line-80"></a>
<a name="line-81"></a><span class='hs-cpp'>#ifdef mingw32_HOST_OS</span>
<a name="line-82"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Typeable</span>
<a name="line-83"></a><span class='hs-cpp'>#endif</span>
<a name="line-84"></a>
<a name="line-85"></a><span class='hs-cpp'>#ifndef mingw32_HOST_OS</span>
<a name="line-86"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Dynamic</span>
<a name="line-87"></a><span class='hs-cpp'>#endif</span>
<a name="line-88"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span>
<a name="line-89"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Maybe</span>
<a name="line-90"></a>
<a name="line-91"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Base</span>
<a name="line-92"></a><span class='hs-keyword'>import</span> <span class='hs-comment'>{-# SOURCE #-}</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Handle</span> <span class='hs-layout'>(</span> <span class='hs-varid'>hFlush</span> <span class='hs-layout'>)</span>
<a name="line-93"></a><span class='hs-keyword'>import</span> <span class='hs-comment'>{-# SOURCE #-}</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Handle</span><span class='hs-varop'>.</span><span class='hs-conid'>FD</span> <span class='hs-layout'>(</span> <span class='hs-varid'>stdout</span> <span class='hs-layout'>)</span>
<a name="line-94"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span>
<a name="line-95"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Exception</span>
<a name="line-96"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Exception</span>
<a name="line-97"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IORef</span>
<a name="line-98"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>MVar</span>
<a name="line-99"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Real</span>         <span class='hs-layout'>(</span> <span class='hs-varid'>fromIntegral</span> <span class='hs-layout'>)</span>
<a name="line-100"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Pack</span>         <span class='hs-layout'>(</span> <span class='hs-varid'>packCString</span><span class='hs-cpp'>#</span> <span class='hs-layout'>)</span>
<a name="line-101"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Show</span>         <span class='hs-layout'>(</span> <span class='hs-conid'>Show</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-varid'>showString</span> <span class='hs-layout'>)</span>
<a name="line-102"></a>
<a name="line-103"></a><span class='hs-keyword'>infixr</span> <span class='hs-num'>0</span> <span class='hs-varop'>`par`</span><span class='hs-layout'>,</span> <span class='hs-varop'>`pseq`</span>
</pre>\end{code}

%************************************************************************
%*                                                                      *
\subsection{@ThreadId@, @par@, and @fork@}
%*                                                                      *
%************************************************************************

\begin{code}
<pre><a name="line-1"></a><a name="ThreadId"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadId</span> <span class='hs-conid'>ThreadId</span><span class='hs-cpp'>#</span> <span class='hs-keyword'>deriving</span><span class='hs-layout'>(</span> <span class='hs-conid'>Typeable</span> <span class='hs-layout'>)</span>
<a name="line-2"></a><span class='hs-comment'>-- ToDo: data ThreadId = ThreadId (Weak ThreadId#)</span>
<a name="line-3"></a><span class='hs-comment'>-- But since ThreadId# is unlifted, the Weak type must use open</span>
<a name="line-4"></a><span class='hs-comment'>-- type variables.</span>
<a name="line-5"></a><span class='hs-comment'>{- ^
<a name="line-6"></a>A 'ThreadId' is an abstract type representing a handle to a thread.
<a name="line-7"></a>'ThreadId' is an instance of 'Eq', 'Ord' and 'Show', where
<a name="line-8"></a>the 'Ord' instance implements an arbitrary total ordering over
<a name="line-9"></a>'ThreadId's. The 'Show' instance lets you convert an arbitrary-valued
<a name="line-10"></a>'ThreadId' to string form; showing a 'ThreadId' value is occasionally
<a name="line-11"></a>useful when debugging or diagnosing the behaviour of a concurrent
<a name="line-12"></a>program.
<a name="line-13"></a>
<a name="line-14"></a>/Note/: in GHC, if you have a 'ThreadId', you essentially have
<a name="line-15"></a>a pointer to the thread itself.  This means the thread itself can\'t be
<a name="line-16"></a>garbage collected until you drop the 'ThreadId'.
<a name="line-17"></a>This misfeature will hopefully be corrected at a later date.
<a name="line-18"></a>
<a name="line-19"></a>/Note/: Hugs does not provide any operations on other threads;
<a name="line-20"></a>it defines 'ThreadId' as a synonym for ().
<a name="line-21"></a>-}</span>
<a name="line-22"></a>
<a name="line-23"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Show</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyword'>where</span>
<a name="line-24"></a>   <span class='hs-varid'>showsPrec</span> <span class='hs-varid'>d</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=</span>
<a name="line-25"></a>        <span class='hs-varid'>showString</span> <span class='hs-str'>"ThreadId "</span> <span class='hs-varop'>.</span>
<a name="line-26"></a>        <span class='hs-varid'>showsPrec</span> <span class='hs-varid'>d</span> <span class='hs-layout'>(</span><span class='hs-varid'>getThreadId</span> <span class='hs-layout'>(</span><span class='hs-varid'>id2TSO</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-27"></a>
<a name="line-28"></a><span class='hs-keyword'>foreign</span> <span class='hs-keyword'>import</span> <span class='hs-keyword'>ccall</span> <span class='hs-keyword'>unsafe</span> <span class='hs-str'>"rts_getThreadId"</span> <span class='hs-varid'>getThreadId</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ThreadId</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>CInt</span>
<a name="line-29"></a>
<a name="line-30"></a><a name="id2TSO"></a><span class='hs-definition'>id2TSO</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ThreadId</span><span class='hs-cpp'>#</span>
<a name="line-31"></a><span class='hs-definition'>id2TSO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ThreadId</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>t</span>
<a name="line-32"></a>
<a name="line-33"></a><span class='hs-keyword'>foreign</span> <span class='hs-keyword'>import</span> <span class='hs-keyword'>ccall</span> <span class='hs-keyword'>unsafe</span> <span class='hs-str'>"cmp_thread"</span> <span class='hs-varid'>cmp_thread</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ThreadId</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ThreadId</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>CInt</span>
<a name="line-34"></a><span class='hs-comment'>-- Returns -1, 0, 1</span>
<a name="line-35"></a>
<a name="line-36"></a><a name="cmpThread"></a><span class='hs-definition'>cmpThread</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Ordering</span>
<a name="line-37"></a><span class='hs-definition'>cmpThread</span> <span class='hs-varid'>t1</span> <span class='hs-varid'>t2</span> <span class='hs-keyglyph'>=</span>
<a name="line-38"></a>   <span class='hs-keyword'>case</span> <span class='hs-varid'>cmp_thread</span> <span class='hs-layout'>(</span><span class='hs-varid'>id2TSO</span> <span class='hs-varid'>t1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>id2TSO</span> <span class='hs-varid'>t2</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span>
<a name="line-39"></a>      <span class='hs-comment'>-</span><span class='hs-num'>1</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>LT</span>
<a name="line-40"></a>      <span class='hs-num'>0</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>EQ</span>
<a name="line-41"></a>      <span class='hs-keyword'>_</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>GT</span> <span class='hs-comment'>-- must be 1</span>
<a name="line-42"></a>
<a name="line-43"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Eq</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyword'>where</span>
<a name="line-44"></a>   <span class='hs-varid'>t1</span> <span class='hs-varop'>==</span> <span class='hs-varid'>t2</span> <span class='hs-keyglyph'>=</span>
<a name="line-45"></a>      <span class='hs-keyword'>case</span> <span class='hs-varid'>t1</span> <span class='hs-varop'>`cmpThread`</span> <span class='hs-varid'>t2</span> <span class='hs-keyword'>of</span>
<a name="line-46"></a>         <span class='hs-conid'>EQ</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>True</span>
<a name="line-47"></a>         <span class='hs-keyword'>_</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>False</span>
<a name="line-48"></a>
<a name="line-49"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Ord</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyword'>where</span>
<a name="line-50"></a>   <span class='hs-varid'>compare</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cmpThread</span>
<a name="line-51"></a>
<a name="line-52"></a><a name="forkIO"></a><span class='hs-comment'>{- |
<a name="line-53"></a>Sparks off a new thread to run the 'IO' computation passed as the
<a name="line-54"></a>first argument, and returns the 'ThreadId' of the newly created
<a name="line-55"></a>thread.
<a name="line-56"></a>
<a name="line-57"></a>The new thread will be a lightweight thread; if you want to use a foreign
<a name="line-58"></a>library that uses thread-local storage, use 'Control.Concurrent.forkOS' instead.
<a name="line-59"></a>
<a name="line-60"></a>GHC note: the new thread inherits the /masked/ state of the parent 
<a name="line-61"></a>(see 'Control.Exception.mask').
<a name="line-62"></a>
<a name="line-63"></a>The newly created thread has an exception handler that discards the
<a name="line-64"></a>exceptions 'BlockedIndefinitelyOnMVar', 'BlockedIndefinitelyOnSTM', and
<a name="line-65"></a>'ThreadKilled', and passes all other exceptions to the uncaught
<a name="line-66"></a>exception handler (see 'setUncaughtExceptionHandler').
<a name="line-67"></a>-}</span>
<a name="line-68"></a><span class='hs-definition'>forkIO</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ThreadId</span>
<a name="line-69"></a><span class='hs-definition'>forkIO</span> <span class='hs-varid'>action</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-70"></a>   <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>fork</span><span class='hs-cpp'>#</span> <span class='hs-varid'>action_plus</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-varid'>tid</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>ThreadId</span> <span class='hs-varid'>tid</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-71"></a> <span class='hs-keyword'>where</span>
<a name="line-72"></a>  <span class='hs-varid'>action_plus</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>catchException</span> <span class='hs-varid'>action</span> <span class='hs-varid'>childHandler</span>
<a name="line-73"></a>
<a name="line-74"></a><a name="forkIOUnmasked"></a><span class='hs-comment'>-- | Like 'forkIO', but the child thread is created with asynchronous exceptions</span>
<a name="line-75"></a><span class='hs-comment'>-- unmasked (see 'Control.Exception.mask').</span>
<a name="line-76"></a><span class='hs-definition'>forkIOUnmasked</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ThreadId</span>
<a name="line-77"></a><span class='hs-definition'>forkIOUnmasked</span> <span class='hs-varid'>io</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>forkIO</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeUnmask</span> <span class='hs-varid'>io</span><span class='hs-layout'>)</span>
<a name="line-78"></a>
<a name="line-79"></a><a name="forkOnIO"></a><span class='hs-comment'>{- |
<a name="line-80"></a>Like 'forkIO', but lets you specify on which CPU the thread is
<a name="line-81"></a>created.  Unlike a `forkIO` thread, a thread created by `forkOnIO`
<a name="line-82"></a>will stay on the same CPU for its entire lifetime (`forkIO` threads
<a name="line-83"></a>can migrate between CPUs according to the scheduling policy).
<a name="line-84"></a>`forkOnIO` is useful for overriding the scheduling policy when you
<a name="line-85"></a>know in advance how best to distribute the threads.
<a name="line-86"></a>
<a name="line-87"></a>The `Int` argument specifies the CPU number; it is interpreted modulo
<a name="line-88"></a>'numCapabilities' (note that it actually specifies a capability number
<a name="line-89"></a>rather than a CPU number, but to a first approximation the two are
<a name="line-90"></a>equivalent).
<a name="line-91"></a>-}</span>
<a name="line-92"></a><span class='hs-definition'>forkOnIO</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ThreadId</span>
<a name="line-93"></a><span class='hs-definition'>forkOnIO</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>cpu</span><span class='hs-layout'>)</span> <span class='hs-varid'>action</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-94"></a>   <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>forkOn</span><span class='hs-cpp'>#</span> <span class='hs-varid'>cpu</span> <span class='hs-varid'>action_plus</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-varid'>tid</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>ThreadId</span> <span class='hs-varid'>tid</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-95"></a> <span class='hs-keyword'>where</span>
<a name="line-96"></a>  <span class='hs-varid'>action_plus</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>catchException</span> <span class='hs-varid'>action</span> <span class='hs-varid'>childHandler</span>
<a name="line-97"></a>
<a name="line-98"></a><a name="forkOnIOUnmasked"></a><span class='hs-comment'>-- | Like 'forkOnIO', but the child thread is created with</span>
<a name="line-99"></a><span class='hs-comment'>-- asynchronous exceptions unmasked (see 'Control.Exception.mask').</span>
<a name="line-100"></a><span class='hs-definition'>forkOnIOUnmasked</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ThreadId</span>
<a name="line-101"></a><span class='hs-definition'>forkOnIOUnmasked</span> <span class='hs-varid'>cpu</span> <span class='hs-varid'>io</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>forkOnIO</span> <span class='hs-varid'>cpu</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeUnmask</span> <span class='hs-varid'>io</span><span class='hs-layout'>)</span>
<a name="line-102"></a>
<a name="line-103"></a><a name="numCapabilities"></a><span class='hs-comment'>-- | the value passed to the @+RTS -N@ flag.  This is the number of</span>
<a name="line-104"></a><span class='hs-comment'>-- Haskell threads that can run truly simultaneously at any given</span>
<a name="line-105"></a><span class='hs-comment'>-- time, and is typically set to the number of physical CPU cores on</span>
<a name="line-106"></a><span class='hs-comment'>-- the machine.</span>
<a name="line-107"></a><span class='hs-definition'>numCapabilities</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span>
<a name="line-108"></a><span class='hs-definition'>numCapabilities</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unsafePerformIO</span> <span class='hs-varop'>$</span>  <span class='hs-keyword'>do</span>
<a name="line-109"></a>                    <span class='hs-varid'>n</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>peek</span> <span class='hs-varid'>n_capabilities</span>
<a name="line-110"></a>                    <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span>
<a name="line-111"></a>
<a name="line-112"></a><a name="numSparks"></a><span class='hs-comment'>-- | Returns the number of sparks currently in the local spark pool</span>
<a name="line-113"></a><span class='hs-definition'>numSparks</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Int</span>
<a name="line-114"></a><span class='hs-definition'>numSparks</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>numSparks</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>n</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>n</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-115"></a>
<a name="line-116"></a><span class='hs-cpp'>#if defined(mingw32_HOST_OS) &amp;&amp; defined(__PIC__)</span>
<a name="line-117"></a><span class='hs-keyword'>foreign</span> <span class='hs-keyword'>import</span> <span class='hs-keyword'>ccall</span> <span class='hs-str'>"_imp__n_capabilities"</span> <span class='hs-varid'>n_capabilities</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>CInt</span>
<a name="line-118"></a><span class='hs-cpp'>#else</span>
<a name="line-119"></a><span class='hs-keyword'>foreign</span> <span class='hs-keyword'>import</span> <span class='hs-keyword'>ccall</span> <span class='hs-str'>"&amp;n_capabilities"</span> <span class='hs-varid'>n_capabilities</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>CInt</span>
<a name="line-120"></a><span class='hs-cpp'>#endif</span>
<a name="line-121"></a><a name="childHandler"></a><span class='hs-definition'>childHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>SomeException</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-122"></a><span class='hs-definition'>childHandler</span> <span class='hs-varid'>err</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>catchException</span> <span class='hs-layout'>(</span><span class='hs-varid'>real_handler</span> <span class='hs-varid'>err</span><span class='hs-layout'>)</span> <span class='hs-varid'>childHandler</span>
<a name="line-123"></a>
<a name="line-124"></a><a name="real_handler"></a><span class='hs-definition'>real_handler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>SomeException</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-125"></a><span class='hs-definition'>real_handler</span> <span class='hs-varid'>se</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>SomeException</span> <span class='hs-varid'>ex</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
<a name="line-126"></a>  <span class='hs-comment'>-- ignore thread GC and killThread exceptions:</span>
<a name="line-127"></a>  <span class='hs-keyword'>case</span> <span class='hs-varid'>cast</span> <span class='hs-varid'>ex</span> <span class='hs-keyword'>of</span>
<a name="line-128"></a>  <span class='hs-conid'>Just</span> <span class='hs-conid'>BlockedIndefinitelyOnMVar</span>        <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
<a name="line-129"></a>  <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>cast</span> <span class='hs-varid'>ex</span> <span class='hs-keyword'>of</span>
<a name="line-130"></a>       <span class='hs-conid'>Just</span> <span class='hs-conid'>BlockedIndefinitelyOnSTM</span>    <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
<a name="line-131"></a>       <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>cast</span> <span class='hs-varid'>ex</span> <span class='hs-keyword'>of</span>
<a name="line-132"></a>            <span class='hs-conid'>Just</span> <span class='hs-conid'>ThreadKilled</span>           <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
<a name="line-133"></a>            <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>cast</span> <span class='hs-varid'>ex</span> <span class='hs-keyword'>of</span>
<a name="line-134"></a>                 <span class='hs-comment'>-- report all others:</span>
<a name="line-135"></a>                 <span class='hs-conid'>Just</span> <span class='hs-conid'>StackOverflow</span>     <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>reportStackOverflow</span>
<a name="line-136"></a>                 <span class='hs-keyword'>_</span>                      <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>reportError</span> <span class='hs-varid'>se</span>
<a name="line-137"></a>
<a name="line-138"></a><a name="killThread"></a><span class='hs-comment'>{- | 'killThread' raises the 'ThreadKilled' exception in the given
<a name="line-139"></a>thread (GHC only).
<a name="line-140"></a>
<a name="line-141"></a>&gt; killThread tid = throwTo tid ThreadKilled
<a name="line-142"></a>
<a name="line-143"></a>-}</span>
<a name="line-144"></a><span class='hs-definition'>killThread</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-145"></a><span class='hs-definition'>killThread</span> <span class='hs-varid'>tid</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>throwTo</span> <span class='hs-varid'>tid</span> <span class='hs-conid'>ThreadKilled</span>
<a name="line-146"></a>
<a name="line-147"></a><a name="throwTo"></a><span class='hs-comment'>{- | 'throwTo' raises an arbitrary exception in the target thread (GHC only).
<a name="line-148"></a>
<a name="line-149"></a>'throwTo' does not return until the exception has been raised in the
<a name="line-150"></a>target thread.
<a name="line-151"></a>The calling thread can thus be certain that the target
<a name="line-152"></a>thread has received the exception.  This is a useful property to know
<a name="line-153"></a>when dealing with race conditions: eg. if there are two threads that
<a name="line-154"></a>can kill each other, it is guaranteed that only one of the threads
<a name="line-155"></a>will get to kill the other.
<a name="line-156"></a>
<a name="line-157"></a>Whatever work the target thread was doing when the exception was
<a name="line-158"></a>raised is not lost: the computation is suspended until required by
<a name="line-159"></a>another thread.
<a name="line-160"></a>
<a name="line-161"></a>If the target thread is currently making a foreign call, then the
<a name="line-162"></a>exception will not be raised (and hence 'throwTo' will not return)
<a name="line-163"></a>until the call has completed.  This is the case regardless of whether
<a name="line-164"></a>the call is inside a 'mask' or not.
<a name="line-165"></a>
<a name="line-166"></a>Important note: the behaviour of 'throwTo' differs from that described in
<a name="line-167"></a>the paper \"Asynchronous exceptions in Haskell\"
<a name="line-168"></a>(&lt;<a href="http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm">http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm</a>&gt;).
<a name="line-169"></a>In the paper, 'throwTo' is non-blocking; but the library implementation adopts
<a name="line-170"></a>a more synchronous design in which 'throwTo' does not return until the exception
<a name="line-171"></a>is received by the target thread.  The trade-off is discussed in Section 9 of the paper.
<a name="line-172"></a>Like any blocking operation, 'throwTo' is therefore interruptible (see Section 5.3 of
<a name="line-173"></a>the paper).  Unlike other interruptible operations, however, 'throwTo'
<a name="line-174"></a>is /always/ interruptible, even if it does not actually block.
<a name="line-175"></a>
<a name="line-176"></a>There is no guarantee that the exception will be delivered promptly,
<a name="line-177"></a>although the runtime will endeavour to ensure that arbitrary
<a name="line-178"></a>delays don't occur.  In GHC, an exception can only be raised when a
<a name="line-179"></a>thread reaches a /safe point/, where a safe point is where memory
<a name="line-180"></a>allocation occurs.  Some loops do not perform any memory allocation
<a name="line-181"></a>inside the loop and therefore cannot be interrupted by a 'throwTo'.
<a name="line-182"></a>
<a name="line-183"></a>Blocked 'throwTo' is fair: if multiple threads are trying to throw an
<a name="line-184"></a>exception to the same target thread, they will succeed in FIFO order.
<a name="line-185"></a>
<a name="line-186"></a>  -}</span>
<a name="line-187"></a><span class='hs-definition'>throwTo</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Exception</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-188"></a><span class='hs-definition'>throwTo</span> <span class='hs-layout'>(</span><span class='hs-conid'>ThreadId</span> <span class='hs-varid'>tid</span><span class='hs-layout'>)</span> <span class='hs-varid'>ex</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-189"></a>   <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>killThread</span><span class='hs-cpp'>#</span> <span class='hs-varid'>tid</span> <span class='hs-layout'>(</span><span class='hs-varid'>toException</span> <span class='hs-varid'>ex</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-varid'>s1</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-190"></a>
<a name="line-191"></a><a name="myThreadId"></a><span class='hs-comment'>-- | Returns the 'ThreadId' of the calling thread (GHC only).</span>
<a name="line-192"></a><span class='hs-definition'>myThreadId</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ThreadId</span>
<a name="line-193"></a><span class='hs-definition'>myThreadId</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-194"></a>   <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>myThreadId</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-varid'>tid</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>ThreadId</span> <span class='hs-varid'>tid</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-195"></a>
<a name="line-196"></a>
<a name="line-197"></a><a name="yield"></a><span class='hs-comment'>-- |The 'yield' action allows (forces, in a co-operative multitasking</span>
<a name="line-198"></a><span class='hs-comment'>-- implementation) a context-switch to any other currently runnable</span>
<a name="line-199"></a><span class='hs-comment'>-- threads (if any), and is occasionally useful when implementing</span>
<a name="line-200"></a><span class='hs-comment'>-- concurrency abstractions.</span>
<a name="line-201"></a><span class='hs-definition'>yield</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-202"></a><span class='hs-definition'>yield</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-203"></a>   <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>yield</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-varid'>s1</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-204"></a>
<a name="line-205"></a><span class='hs-comment'>{- | 'labelThread' stores a string as identifier for this thread if
<a name="line-206"></a>you built a RTS with debugging support. This identifier will be used in
<a name="line-207"></a>the debugging output to make distinction of different threads easier
<a name="line-208"></a>(otherwise you only have the thread state object\'s address in the heap).
<a name="line-209"></a>
<a name="line-210"></a>Other applications like the graphical Concurrent Haskell Debugger
<a name="line-211"></a>(&lt;<a href="http://www.informatik.uni-kiel.de/~fhu/chd/">http://www.informatik.uni-kiel.de/~fhu/chd/</a>&gt;) may choose to overload
<a name="line-212"></a>'labelThread' for their purposes as well.
<a name="line-213"></a>-}</span>
<a name="line-214"></a>
<a name="line-215"></a><a name="labelThread"></a><span class='hs-definition'>labelThread</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-216"></a><span class='hs-definition'>labelThread</span> <span class='hs-layout'>(</span><span class='hs-conid'>ThreadId</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-varid'>str</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-217"></a>   <span class='hs-keyword'>let</span> <span class='hs-varop'>!</span><span class='hs-varid'>ps</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>packCString</span><span class='hs-cpp'>#</span> <span class='hs-varid'>str</span>
<a name="line-218"></a>       <span class='hs-varop'>!</span><span class='hs-varid'>adr</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>byteArrayContents</span><span class='hs-cpp'>#</span> <span class='hs-varid'>ps</span> <span class='hs-keyword'>in</span>
<a name="line-219"></a>     <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>labelThread</span><span class='hs-cpp'>#</span> <span class='hs-varid'>t</span> <span class='hs-varid'>adr</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-varid'>s1</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-220"></a>
<a name="line-221"></a><span class='hs-comment'>--      Nota Bene: 'pseq' used to be 'seq'</span>
<a name="line-222"></a><span class='hs-comment'>--                 but 'seq' is now defined in PrelGHC</span>
<a name="line-223"></a><span class='hs-comment'>--</span>
<a name="line-224"></a><span class='hs-comment'>-- "pseq" is defined a bit weirdly (see below)</span>
<a name="line-225"></a><span class='hs-comment'>--</span>
<a name="line-226"></a><span class='hs-comment'>-- The reason for the strange "lazy" call is that</span>
<a name="line-227"></a><span class='hs-comment'>-- it fools the compiler into thinking that pseq  and par are non-strict in</span>
<a name="line-228"></a><span class='hs-comment'>-- their second argument (even if it inlines pseq at the call site).</span>
<a name="line-229"></a><span class='hs-comment'>-- If it thinks pseq is strict in "y", then it often evaluates</span>
<a name="line-230"></a><span class='hs-comment'>-- "y" before "x", which is totally wrong.</span>
<a name="line-231"></a>
<a name="line-232"></a><a name="pseq"></a><span class='hs-comment'>{-# INLINE pseq  #-}</span>
<a name="line-233"></a><span class='hs-definition'>pseq</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span>
<a name="line-234"></a><span class='hs-definition'>pseq</span>  <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span> <span class='hs-varop'>`seq`</span> <span class='hs-varid'>lazy</span> <span class='hs-varid'>y</span>
<a name="line-235"></a>
<a name="line-236"></a><a name="par"></a><span class='hs-comment'>{-# INLINE par  #-}</span>
<a name="line-237"></a><span class='hs-definition'>par</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span>
<a name="line-238"></a><span class='hs-definition'>par</span>  <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>par</span><span class='hs-cpp'>#</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>lazy</span> <span class='hs-varid'>y</span> <span class='hs-layout'>}</span>
<a name="line-239"></a>
<a name="line-240"></a><a name="runSparks"></a><span class='hs-comment'>-- | Internal function used by the RTS to run sparks.</span>
<a name="line-241"></a><span class='hs-definition'>runSparks</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-242"></a><span class='hs-definition'>runSparks</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>loop</span>
<a name="line-243"></a>  <span class='hs-keyword'>where</span> <span class='hs-varid'>loop</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>getSpark</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-244"></a>                   <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>n</span><span class='hs-layout'>,</span> <span class='hs-varid'>p</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-245"></a>                      <span class='hs-keyword'>if</span> <span class='hs-varid'>n</span> <span class='hs-varop'>==#</span> <span class='hs-num'>0</span><span class='hs-cpp'>#</span> <span class='hs-keyword'>then</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-246"></a>                                  <span class='hs-keyword'>else</span> <span class='hs-varid'>p</span> <span class='hs-varop'>`seq`</span> <span class='hs-varid'>loop</span> <span class='hs-varid'>s'</span>
<a name="line-247"></a>
<a name="line-248"></a><a name="BlockReason"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>BlockReason</span>
<a name="line-249"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>BlockedOnMVar</span>
<a name="line-250"></a>        <span class='hs-comment'>-- ^blocked on on 'MVar'</span>
<a name="line-251"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>BlockedOnBlackHole</span>
<a name="line-252"></a>        <span class='hs-comment'>-- ^blocked on a computation in progress by another thread</span>
<a name="line-253"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>BlockedOnException</span>
<a name="line-254"></a>        <span class='hs-comment'>-- ^blocked in 'throwTo'</span>
<a name="line-255"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>BlockedOnSTM</span>
<a name="line-256"></a>        <span class='hs-comment'>-- ^blocked in 'retry' in an STM transaction</span>
<a name="line-257"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>BlockedOnForeignCall</span>
<a name="line-258"></a>        <span class='hs-comment'>-- ^currently in a foreign call</span>
<a name="line-259"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>BlockedOnOther</span>
<a name="line-260"></a>        <span class='hs-comment'>-- ^blocked on some other resource.  Without @-threaded@,</span>
<a name="line-261"></a>        <span class='hs-comment'>-- I\/O and 'threadDelay' show up as 'BlockedOnOther', with @-threaded@</span>
<a name="line-262"></a>        <span class='hs-comment'>-- they show up as 'BlockedOnMVar'.</span>
<a name="line-263"></a>  <span class='hs-keyword'>deriving</span> <span class='hs-layout'>(</span><span class='hs-conid'>Eq</span><span class='hs-layout'>,</span><span class='hs-conid'>Ord</span><span class='hs-layout'>,</span><span class='hs-conid'>Show</span><span class='hs-layout'>)</span>
<a name="line-264"></a>
<a name="line-265"></a><a name="ThreadStatus"></a><span class='hs-comment'>-- | The current status of a thread</span>
<a name="line-266"></a><a name="ThreadStatus"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>ThreadStatus</span>
<a name="line-267"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadRunning</span>
<a name="line-268"></a>        <span class='hs-comment'>-- ^the thread is currently runnable or running</span>
<a name="line-269"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>ThreadFinished</span>
<a name="line-270"></a>        <span class='hs-comment'>-- ^the thread has finished</span>
<a name="line-271"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>ThreadBlocked</span>  <span class='hs-conid'>BlockReason</span>
<a name="line-272"></a>        <span class='hs-comment'>-- ^the thread is blocked on some resource</span>
<a name="line-273"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-conid'>ThreadDied</span>
<a name="line-274"></a>        <span class='hs-comment'>-- ^the thread received an uncaught exception</span>
<a name="line-275"></a>  <span class='hs-keyword'>deriving</span> <span class='hs-layout'>(</span><span class='hs-conid'>Eq</span><span class='hs-layout'>,</span><span class='hs-conid'>Ord</span><span class='hs-layout'>,</span><span class='hs-conid'>Show</span><span class='hs-layout'>)</span>
<a name="line-276"></a>
<a name="line-277"></a><a name="threadStatus"></a><span class='hs-definition'>threadStatus</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ThreadId</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ThreadStatus</span>
<a name="line-278"></a><span class='hs-definition'>threadStatus</span> <span class='hs-layout'>(</span><span class='hs-conid'>ThreadId</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-279"></a>   <span class='hs-keyword'>case</span> <span class='hs-varid'>threadStatus</span><span class='hs-cpp'>#</span> <span class='hs-varid'>t</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-280"></a>     <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>stat</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>mk_stat</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>stat</span><span class='hs-layout'>)</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-281"></a>   <span class='hs-keyword'>where</span>
<a name="line-282"></a>        <span class='hs-comment'>-- NB. keep these in sync with includes/Constants.h</span>
<a name="line-283"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>0</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadRunning</span>
<a name="line-284"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>1</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadBlocked</span> <span class='hs-conid'>BlockedOnMVar</span>
<a name="line-285"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>2</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadBlocked</span> <span class='hs-conid'>BlockedOnBlackHole</span>
<a name="line-286"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>3</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadBlocked</span> <span class='hs-conid'>BlockedOnException</span>
<a name="line-287"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>7</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadBlocked</span> <span class='hs-conid'>BlockedOnSTM</span>
<a name="line-288"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>11</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadBlocked</span> <span class='hs-conid'>BlockedOnForeignCall</span>
<a name="line-289"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>12</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadBlocked</span> <span class='hs-conid'>BlockedOnForeignCall</span>
<a name="line-290"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>16</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadFinished</span>
<a name="line-291"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-num'>17</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadDied</span>
<a name="line-292"></a>     <span class='hs-varid'>mk_stat</span> <span class='hs-keyword'>_</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ThreadBlocked</span> <span class='hs-conid'>BlockedOnOther</span>
</pre>\end{code}


%************************************************************************
%*                                                                      *
\subsection[stm]{Transactional heap operations}
%*                                                                      *
%************************************************************************

TVars are shared memory locations which support atomic memory
transactions.

\begin{code}
<pre><a name="line-1"></a><a name="STM"></a><span class='hs-comment'>-- |A monad supporting atomic memory transactions.</span>
<a name="line-2"></a><a name="STM"></a><span class='hs-keyword'>newtype</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>State</span><span class='hs-cpp'>#</span> <span class='hs-conid'>RealWorld</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-conid'>State</span><span class='hs-cpp'>#</span> <span class='hs-conid'>RealWorld</span><span class='hs-layout'>,</span> <span class='hs-varid'>a</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-3"></a>
<a name="line-4"></a><a name="unSTM"></a><span class='hs-definition'>unSTM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>State</span><span class='hs-cpp'>#</span> <span class='hs-conid'>RealWorld</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-conid'>State</span><span class='hs-cpp'>#</span> <span class='hs-conid'>RealWorld</span><span class='hs-layout'>,</span> <span class='hs-varid'>a</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-5"></a><span class='hs-definition'>unSTM</span> <span class='hs-layout'>(</span><span class='hs-conid'>STM</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>a</span>
<a name="line-6"></a>
<a name="line-7"></a><span class='hs-conid'>INSTANCE_TYPEABLE1</span><span class='hs-layout'>(</span><span class='hs-conid'>STM</span><span class='hs-layout'>,</span><span class='hs-varid'>stmTc</span><span class='hs-layout'>,</span><span class='hs-str'>"STM"</span><span class='hs-layout'>)</span>
<a name="line-8"></a>
<a name="line-9"></a><span class='hs-keyword'>instance</span>  <span class='hs-conid'>Functor</span> <span class='hs-conid'>STM</span> <span class='hs-keyword'>where</span>
<a name="line-10"></a>   <span class='hs-varid'>fmap</span> <span class='hs-varid'>f</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span> <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-layout'>(</span><span class='hs-varid'>return</span> <span class='hs-varop'>.</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span>
<a name="line-11"></a>
<a name="line-12"></a><span class='hs-keyword'>instance</span>  <span class='hs-conid'>Monad</span> <span class='hs-conid'>STM</span>  <span class='hs-keyword'>where</span>
<a name="line-13"></a>    <span class='hs-comment'>{-# INLINE return #-}</span>
<a name="line-14"></a>    <span class='hs-comment'>{-# INLINE (&gt;&gt;)   #-}</span>
<a name="line-15"></a>    <span class='hs-comment'>{-# INLINE (&gt;&gt;=)  #-}</span>
<a name="line-16"></a>    <span class='hs-varid'>m</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>k</span>      <span class='hs-keyglyph'>=</span> <span class='hs-varid'>thenSTM</span> <span class='hs-varid'>m</span> <span class='hs-varid'>k</span>
<a name="line-17"></a>    <span class='hs-varid'>return</span> <span class='hs-varid'>x</span>    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>returnSTM</span> <span class='hs-varid'>x</span>
<a name="line-18"></a>    <span class='hs-varid'>m</span> <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-varid'>k</span>     <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bindSTM</span> <span class='hs-varid'>m</span> <span class='hs-varid'>k</span>
<a name="line-19"></a>
<a name="line-20"></a><a name="bindSTM"></a><span class='hs-definition'>bindSTM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>b</span>
<a name="line-21"></a><span class='hs-definition'>bindSTM</span> <span class='hs-layout'>(</span><span class='hs-conid'>STM</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-varid'>k</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-22"></a>  <span class='hs-keyword'>case</span> <span class='hs-varid'>m</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-23"></a>    <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>new_s</span><span class='hs-layout'>,</span> <span class='hs-varid'>a</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>unSTM</span> <span class='hs-layout'>(</span><span class='hs-varid'>k</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-varid'>new_s</span>
<a name="line-24"></a>  <span class='hs-layout'>)</span>
<a name="line-25"></a>
<a name="line-26"></a><a name="thenSTM"></a><span class='hs-definition'>thenSTM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>b</span>
<a name="line-27"></a><span class='hs-definition'>thenSTM</span> <span class='hs-layout'>(</span><span class='hs-conid'>STM</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-varid'>k</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-28"></a>  <span class='hs-keyword'>case</span> <span class='hs-varid'>m</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-29"></a>    <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>new_s</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>unSTM</span> <span class='hs-varid'>k</span> <span class='hs-varid'>new_s</span>
<a name="line-30"></a>  <span class='hs-layout'>)</span>
<a name="line-31"></a>
<a name="line-32"></a><a name="returnSTM"></a><span class='hs-definition'>returnSTM</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span>
<a name="line-33"></a><span class='hs-definition'>returnSTM</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span><span class='hs-layout'>,</span> <span class='hs-varid'>x</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-34"></a>
<a name="line-35"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>MonadPlus</span> <span class='hs-conid'>STM</span> <span class='hs-keyword'>where</span>
<a name="line-36"></a>  <span class='hs-varid'>mzero</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>retry</span>
<a name="line-37"></a>  <span class='hs-varid'>mplus</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>orElse</span>
<a name="line-38"></a>
<a name="line-39"></a><a name="unsafeIOToSTM"></a><span class='hs-comment'>-- | Unsafely performs IO in the STM monad.  Beware: this is a highly</span>
<a name="line-40"></a><span class='hs-comment'>-- dangerous thing to do.</span>
<a name="line-41"></a><span class='hs-comment'>--</span>
<a name="line-42"></a><span class='hs-comment'>--   * The STM implementation will often run transactions multiple</span>
<a name="line-43"></a><span class='hs-comment'>--     times, so you need to be prepared for this if your IO has any</span>
<a name="line-44"></a><span class='hs-comment'>--     side effects.</span>
<a name="line-45"></a><span class='hs-comment'>--</span>
<a name="line-46"></a><span class='hs-comment'>--   * The STM implementation will abort transactions that are known to</span>
<a name="line-47"></a><span class='hs-comment'>--     be invalid and need to be restarted.  This may happen in the middle</span>
<a name="line-48"></a><span class='hs-comment'>--     of `unsafeIOToSTM`, so make sure you don't acquire any resources</span>
<a name="line-49"></a><span class='hs-comment'>--     that need releasing (exception handlers are ignored when aborting</span>
<a name="line-50"></a><span class='hs-comment'>--     the transaction).  That includes doing any IO using Handles, for</span>
<a name="line-51"></a><span class='hs-comment'>--     example.  Getting this wrong will probably lead to random deadlocks.</span>
<a name="line-52"></a><span class='hs-comment'>--</span>
<a name="line-53"></a><span class='hs-comment'>--   * The transaction may have seen an inconsistent view of memory when</span>
<a name="line-54"></a><span class='hs-comment'>--     the IO runs.  Invariants that you expect to be true throughout</span>
<a name="line-55"></a><span class='hs-comment'>--     your program may not be true inside a transaction, due to the</span>
<a name="line-56"></a><span class='hs-comment'>--     way transactions are implemented.  Normally this wouldn't be visible</span>
<a name="line-57"></a><span class='hs-comment'>--     to the programmer, but using `unsafeIOToSTM` can expose it.</span>
<a name="line-58"></a><span class='hs-comment'>--</span>
<a name="line-59"></a><span class='hs-definition'>unsafeIOToSTM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span>
<a name="line-60"></a><span class='hs-definition'>unsafeIOToSTM</span> <span class='hs-layout'>(</span><span class='hs-conid'>IO</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>m</span>
<a name="line-61"></a>
<a name="line-62"></a><span class='hs-comment'>-- |Perform a series of STM actions atomically.</span>
<a name="line-63"></a><span class='hs-comment'>--</span>
<a name="line-64"></a><span class='hs-comment'>-- You cannot use 'atomically' inside an 'unsafePerformIO' or 'unsafeInterleaveIO'.</span>
<a name="line-65"></a><span class='hs-comment'>-- Any attempt to do so will result in a runtime error.  (Reason: allowing</span>
<a name="line-66"></a><span class='hs-comment'>-- this would effectively allow a transaction inside a transaction, depending</span>
<a name="line-67"></a><span class='hs-comment'>-- on exactly when the thunk is evaluated.)</span>
<a name="line-68"></a><span class='hs-comment'>--</span>
<a name="line-69"></a><span class='hs-comment'>-- However, see 'newTVarIO', which can be called inside 'unsafePerformIO',</span>
<a name="line-70"></a><span class='hs-comment'>-- and which allows top-level TVars to be allocated.</span>
<a name="line-71"></a>
<a name="line-72"></a><a name="atomically"></a><span class='hs-definition'>atomically</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
<a name="line-73"></a><span class='hs-definition'>atomically</span> <span class='hs-layout'>(</span><span class='hs-conid'>STM</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>atomically</span><span class='hs-cpp'>#</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span> <span class='hs-layout'>)</span>
<a name="line-74"></a>
<a name="line-75"></a><a name="retry"></a><span class='hs-comment'>-- |Retry execution of the current memory transaction because it has seen</span>
<a name="line-76"></a><span class='hs-comment'>-- values in TVars which mean that it should not continue (e.g. the TVars</span>
<a name="line-77"></a><span class='hs-comment'>-- represent a shared buffer that is now empty).  The implementation may</span>
<a name="line-78"></a><span class='hs-comment'>-- block the thread until one of the TVars that it has read from has been</span>
<a name="line-79"></a><span class='hs-comment'>-- udpated. (GHC only)</span>
<a name="line-80"></a><span class='hs-definition'>retry</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span>
<a name="line-81"></a><span class='hs-definition'>retry</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>retry</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span><span class='hs-cpp'>#</span>
<a name="line-82"></a>
<a name="line-83"></a><a name="orElse"></a><span class='hs-comment'>-- |Compose two alternative STM actions (GHC only).  If the first action</span>
<a name="line-84"></a><span class='hs-comment'>-- completes without retrying then it forms the result of the orElse.</span>
<a name="line-85"></a><span class='hs-comment'>-- Otherwise, if the first action retries, then the second action is</span>
<a name="line-86"></a><span class='hs-comment'>-- tried in its place.  If both actions retry then the orElse as a</span>
<a name="line-87"></a><span class='hs-comment'>-- whole retries.</span>
<a name="line-88"></a><span class='hs-definition'>orElse</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span>
<a name="line-89"></a><span class='hs-definition'>orElse</span> <span class='hs-layout'>(</span><span class='hs-conid'>STM</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>catchRetry</span><span class='hs-cpp'>#</span> <span class='hs-varid'>m</span> <span class='hs-layout'>(</span><span class='hs-varid'>unSTM</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
<a name="line-90"></a>
<a name="line-91"></a><a name="throwSTM"></a><span class='hs-comment'>-- | A variant of 'throw' that can only be used within the 'STM' monad.</span>
<a name="line-92"></a><span class='hs-comment'>--</span>
<a name="line-93"></a><span class='hs-comment'>-- Throwing an exception in @STM@ aborts the transaction and propagates the</span>
<a name="line-94"></a><span class='hs-comment'>-- exception.</span>
<a name="line-95"></a><span class='hs-comment'>--</span>
<a name="line-96"></a><span class='hs-comment'>-- Although 'throwSTM' has a type that is an instance of the type of 'throw', the</span>
<a name="line-97"></a><span class='hs-comment'>-- two functions are subtly different:</span>
<a name="line-98"></a><span class='hs-comment'>--</span>
<a name="line-99"></a><span class='hs-comment'>-- &gt; throw e    `seq` x  ===&gt; throw e</span>
<a name="line-100"></a><span class='hs-comment'>-- &gt; throwSTM e `seq` x  ===&gt; x</span>
<a name="line-101"></a><span class='hs-comment'>--</span>
<a name="line-102"></a><span class='hs-comment'>-- The first example will cause the exception @e@ to be raised,</span>
<a name="line-103"></a><span class='hs-comment'>-- whereas the second one won\'t.  In fact, 'throwSTM' will only cause</span>
<a name="line-104"></a><span class='hs-comment'>-- an exception to be raised when it is used within the 'STM' monad.</span>
<a name="line-105"></a><span class='hs-comment'>-- The 'throwSTM' variant should be used in preference to 'throw' to</span>
<a name="line-106"></a><span class='hs-comment'>-- raise an exception within the 'STM' monad because it guarantees</span>
<a name="line-107"></a><span class='hs-comment'>-- ordering with respect to other 'STM' operations, whereas 'throw'</span>
<a name="line-108"></a><span class='hs-comment'>-- does not.</span>
<a name="line-109"></a><span class='hs-definition'>throwSTM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Exception</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span>
<a name="line-110"></a><span class='hs-definition'>throwSTM</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varop'>$</span> <span class='hs-varid'>raiseIO</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>toException</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
<a name="line-111"></a>
<a name="line-112"></a><a name="catchSTM"></a><span class='hs-comment'>-- |Exception handling within STM actions.</span>
<a name="line-113"></a><span class='hs-definition'>catchSTM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Exception</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span>
<a name="line-114"></a><span class='hs-definition'>catchSTM</span> <span class='hs-layout'>(</span><span class='hs-conid'>STM</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-varid'>handler</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varop'>$</span> <span class='hs-varid'>catchSTM</span><span class='hs-cpp'>#</span> <span class='hs-varid'>m</span> <span class='hs-varid'>handler'</span>
<a name="line-115"></a>    <span class='hs-keyword'>where</span>
<a name="line-116"></a>      <span class='hs-varid'>handler'</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>fromException</span> <span class='hs-varid'>e</span> <span class='hs-keyword'>of</span>
<a name="line-117"></a>                     <span class='hs-conid'>Just</span> <span class='hs-varid'>e'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>unSTM</span> <span class='hs-layout'>(</span><span class='hs-varid'>handler</span> <span class='hs-varid'>e'</span><span class='hs-layout'>)</span>
<a name="line-118"></a>                     <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>raiseIO</span><span class='hs-cpp'>#</span> <span class='hs-varid'>e</span>
<a name="line-119"></a>
<a name="line-120"></a><a name="checkInv"></a><span class='hs-comment'>-- | Low-level primitive on which always and alwaysSucceeds are built.</span>
<a name="line-121"></a><span class='hs-comment'>-- checkInv differs form these in that (i) the invariant is not</span>
<a name="line-122"></a><span class='hs-comment'>-- checked when checkInv is called, only at the end of this and</span>
<a name="line-123"></a><span class='hs-comment'>-- subsequent transcations, (ii) the invariant failure is indicated</span>
<a name="line-124"></a><span class='hs-comment'>-- by raising an exception.</span>
<a name="line-125"></a><span class='hs-definition'>checkInv</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>()</span>
<a name="line-126"></a><span class='hs-definition'>checkInv</span> <span class='hs-layout'>(</span><span class='hs-conid'>STM</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>check</span><span class='hs-cpp'>#</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-127"></a>
<a name="line-128"></a><a name="alwaysSucceeds"></a><span class='hs-comment'>-- | alwaysSucceeds adds a new invariant that must be true when passed</span>
<a name="line-129"></a><span class='hs-comment'>-- to alwaysSucceeds, at the end of the current transaction, and at</span>
<a name="line-130"></a><span class='hs-comment'>-- the end of every subsequent transaction.  If it fails at any</span>
<a name="line-131"></a><span class='hs-comment'>-- of those points then the transaction violating it is aborted</span>
<a name="line-132"></a><span class='hs-comment'>-- and the exception raised by the invariant is propagated.</span>
<a name="line-133"></a><span class='hs-definition'>alwaysSucceeds</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>()</span>
<a name="line-134"></a><span class='hs-definition'>alwaysSucceeds</span> <span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <span class='hs-layout'>(</span> <span class='hs-varid'>i</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>retry</span> <span class='hs-layout'>)</span> <span class='hs-varop'>`orElse`</span> <span class='hs-layout'>(</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <span class='hs-layout'>)</span>
<a name="line-135"></a>                      <span class='hs-varid'>checkInv</span> <span class='hs-varid'>i</span>
<a name="line-136"></a>
<a name="line-137"></a><a name="always"></a><span class='hs-comment'>-- | always is a variant of alwaysSucceeds in which the invariant is</span>
<a name="line-138"></a><span class='hs-comment'>-- expressed as an STM Bool action that must return True.  Returning</span>
<a name="line-139"></a><span class='hs-comment'>-- False or raising an exception are both treated as invariant failures.</span>
<a name="line-140"></a><span class='hs-definition'>always</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>()</span>
<a name="line-141"></a><span class='hs-definition'>always</span> <span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>alwaysSucceeds</span> <span class='hs-layout'>(</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>i</span>
<a name="line-142"></a>                               <span class='hs-keyword'>if</span> <span class='hs-layout'>(</span><span class='hs-varid'>v</span><span class='hs-layout'>)</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <span class='hs-keyword'>else</span> <span class='hs-layout'>(</span> <span class='hs-varid'>error</span> <span class='hs-str'>"Transacional invariant violation"</span> <span class='hs-layout'>)</span> <span class='hs-layout'>)</span>
<a name="line-143"></a>
<a name="line-144"></a><a name="TVar"></a><span class='hs-comment'>-- |Shared memory locations that support atomic memory transactions.</span>
<a name="line-145"></a><a name="TVar"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>TVar</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span><span class='hs-cpp'>#</span> <span class='hs-conid'>RealWorld</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-146"></a>
<a name="line-147"></a><span class='hs-conid'>INSTANCE_TYPEABLE1</span><span class='hs-layout'>(</span><span class='hs-conid'>TVar</span><span class='hs-layout'>,</span><span class='hs-varid'>tvarTc</span><span class='hs-layout'>,</span><span class='hs-str'>"TVar"</span><span class='hs-layout'>)</span>
<a name="line-148"></a>
<a name="line-149"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Eq</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-150"></a>        <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>tvar1</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-varop'>==</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>tvar2</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sameTVar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>tvar1</span><span class='hs-cpp'>#</span> <span class='hs-varid'>tvar2</span><span class='hs-cpp'>#</span>
<a name="line-151"></a>
<a name="line-152"></a><a name="newTVar"></a><span class='hs-comment'>-- |Create a new TVar holding a value supplied</span>
<a name="line-153"></a><span class='hs-definition'>newTVar</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-154"></a><span class='hs-definition'>newTVar</span> <span class='hs-varid'>val</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s1</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-155"></a>    <span class='hs-keyword'>case</span> <span class='hs-varid'>newTVar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>val</span> <span class='hs-varid'>s1</span><span class='hs-cpp'>#</span> <span class='hs-keyword'>of</span>
<a name="line-156"></a>         <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s2</span><span class='hs-cpp'>#</span><span class='hs-layout'>,</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s2</span><span class='hs-cpp'>#</span><span class='hs-layout'>,</span> <span class='hs-conid'>TVar</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-157"></a>
<a name="line-158"></a><a name="newTVarIO"></a><span class='hs-comment'>-- |@IO@ version of 'newTVar'.  This is useful for creating top-level</span>
<a name="line-159"></a><span class='hs-comment'>-- 'TVar's using 'System.IO.Unsafe.unsafePerformIO', because using</span>
<a name="line-160"></a><span class='hs-comment'>-- 'atomically' inside 'System.IO.Unsafe.unsafePerformIO' isn't</span>
<a name="line-161"></a><span class='hs-comment'>-- possible.</span>
<a name="line-162"></a><span class='hs-definition'>newTVarIO</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-163"></a><span class='hs-definition'>newTVarIO</span> <span class='hs-varid'>val</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s1</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-164"></a>    <span class='hs-keyword'>case</span> <span class='hs-varid'>newTVar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>val</span> <span class='hs-varid'>s1</span><span class='hs-cpp'>#</span> <span class='hs-keyword'>of</span>
<a name="line-165"></a>         <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s2</span><span class='hs-cpp'>#</span><span class='hs-layout'>,</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s2</span><span class='hs-cpp'>#</span><span class='hs-layout'>,</span> <span class='hs-conid'>TVar</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-166"></a>
<a name="line-167"></a><a name="readTVarIO"></a><span class='hs-comment'>-- |Return the current value stored in a TVar.</span>
<a name="line-168"></a><span class='hs-comment'>-- This is equivalent to</span>
<a name="line-169"></a><span class='hs-comment'>--</span>
<a name="line-170"></a><span class='hs-comment'>-- &gt;  readTVarIO = atomically . readTVar</span>
<a name="line-171"></a><span class='hs-comment'>--</span>
<a name="line-172"></a><span class='hs-comment'>-- but works much faster, because it doesn't perform a complete</span>
<a name="line-173"></a><span class='hs-comment'>-- transaction, it just reads the current value of the 'TVar'.</span>
<a name="line-174"></a><span class='hs-definition'>readTVarIO</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TVar</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
<a name="line-175"></a><span class='hs-definition'>readTVarIO</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>readTVarIO</span><span class='hs-cpp'>#</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span><span class='hs-cpp'>#</span>
<a name="line-176"></a>
<a name="line-177"></a><a name="readTVar"></a><span class='hs-comment'>-- |Return the current value stored in a TVar</span>
<a name="line-178"></a><span class='hs-definition'>readTVar</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TVar</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-varid'>a</span>
<a name="line-179"></a><span class='hs-definition'>readTVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>readTVar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span><span class='hs-cpp'>#</span>
<a name="line-180"></a>
<a name="line-181"></a><a name="writeTVar"></a><span class='hs-comment'>-- |Write the supplied value into a TVar</span>
<a name="line-182"></a><span class='hs-definition'>writeTVar</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TVar</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>STM</span> <span class='hs-conid'>()</span>
<a name="line-183"></a><span class='hs-definition'>writeTVar</span> <span class='hs-layout'>(</span><span class='hs-conid'>TVar</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-varid'>val</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>STM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s1</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-184"></a>    <span class='hs-keyword'>case</span> <span class='hs-varid'>writeTVar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>tvar</span><span class='hs-cpp'>#</span> <span class='hs-varid'>val</span> <span class='hs-varid'>s1</span><span class='hs-cpp'>#</span> <span class='hs-keyword'>of</span>
<a name="line-185"></a>         <span class='hs-varid'>s2</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s2</span><span class='hs-cpp'>#</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span>
<a name="line-186"></a>
</pre>\end{code}

MVar utilities

\begin{code}
<pre><a name="line-1"></a><a name="withMVar"></a><span class='hs-definition'>withMVar</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>MVar</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>b</span>
<a name="line-2"></a><span class='hs-definition'>withMVar</span> <span class='hs-varid'>m</span> <span class='hs-varid'>io</span> <span class='hs-keyglyph'>=</span>
<a name="line-3"></a>  <span class='hs-varid'>mask</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>restore</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-4"></a>    <span class='hs-varid'>a</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>takeMVar</span> <span class='hs-varid'>m</span>
<a name="line-5"></a>    <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>catchAny</span> <span class='hs-layout'>(</span><span class='hs-varid'>restore</span> <span class='hs-layout'>(</span><span class='hs-varid'>io</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-6"></a>            <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>e</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>putMVar</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a</span><span class='hs-layout'>;</span> <span class='hs-varid'>throw</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
<a name="line-7"></a>    <span class='hs-varid'>putMVar</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a</span>
<a name="line-8"></a>    <span class='hs-varid'>return</span> <span class='hs-varid'>b</span>
<a name="line-9"></a>
<a name="line-10"></a><a name="modifyMVar_"></a><span class='hs-definition'>modifyMVar_</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>MVar</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-11"></a><span class='hs-definition'>modifyMVar_</span> <span class='hs-varid'>m</span> <span class='hs-varid'>io</span> <span class='hs-keyglyph'>=</span>
<a name="line-12"></a>  <span class='hs-varid'>mask</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>restore</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-13"></a>    <span class='hs-varid'>a</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>takeMVar</span> <span class='hs-varid'>m</span>
<a name="line-14"></a>    <span class='hs-varid'>a'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>catchAny</span> <span class='hs-layout'>(</span><span class='hs-varid'>restore</span> <span class='hs-layout'>(</span><span class='hs-varid'>io</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-15"></a>            <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>e</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>putMVar</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a</span><span class='hs-layout'>;</span> <span class='hs-varid'>throw</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
<a name="line-16"></a>    <span class='hs-varid'>putMVar</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a'</span>
<a name="line-17"></a>    <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
</pre>\end{code}

%************************************************************************
%*                                                                      *
\subsection{Thread waiting}
%*                                                                      *
%************************************************************************

\begin{code}
<pre><a name="line-1"></a>
<a name="line-2"></a><a name="sharedCAF"></a><span class='hs-comment'>-- Machinery needed to ensureb that we only have one copy of certain</span>
<a name="line-3"></a><span class='hs-comment'>-- CAFs in this module even when the base package is present twice, as</span>
<a name="line-4"></a><span class='hs-comment'>-- it is when base is dynamically loaded into GHCi.  The RTS keeps</span>
<a name="line-5"></a><span class='hs-comment'>-- track of the single true value of the CAF, so even when the CAFs in</span>
<a name="line-6"></a><span class='hs-comment'>-- the dynamically-loaded base package are reverted, nothing bad</span>
<a name="line-7"></a><span class='hs-comment'>-- happens.</span>
<a name="line-8"></a><span class='hs-comment'>--</span>
<a name="line-9"></a><span class='hs-definition'>sharedCAF</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
<a name="line-10"></a><span class='hs-definition'>sharedCAF</span> <span class='hs-varid'>a</span> <span class='hs-varid'>get_or_set</span> <span class='hs-keyglyph'>=</span>
<a name="line-11"></a>   <span class='hs-varid'>mask_</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
<a name="line-12"></a>     <span class='hs-varid'>stable_ref</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newStablePtr</span> <span class='hs-varid'>a</span>
<a name="line-13"></a>     <span class='hs-keyword'>let</span> <span class='hs-varid'>ref</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>castPtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>castStablePtrToPtr</span> <span class='hs-varid'>stable_ref</span><span class='hs-layout'>)</span>
<a name="line-14"></a>     <span class='hs-varid'>ref2</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>get_or_set</span> <span class='hs-varid'>ref</span>
<a name="line-15"></a>     <span class='hs-keyword'>if</span> <span class='hs-varid'>ref</span><span class='hs-varop'>==</span><span class='hs-varid'>ref2</span>
<a name="line-16"></a>        <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-varid'>a</span>
<a name="line-17"></a>        <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>freeStablePtr</span> <span class='hs-varid'>stable_ref</span>
<a name="line-18"></a>                <span class='hs-varid'>deRefStablePtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtrToStablePtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span> <span class='hs-varid'>ref2</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-19"></a>
<a name="line-20"></a><a name="reportStackOverflow"></a><span class='hs-definition'>reportStackOverflow</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-21"></a><span class='hs-definition'>reportStackOverflow</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>callStackOverflowHook</span>
<a name="line-22"></a>
<a name="line-23"></a><a name="reportError"></a><span class='hs-definition'>reportError</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>SomeException</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-24"></a><span class='hs-definition'>reportError</span> <span class='hs-varid'>ex</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-25"></a>   <span class='hs-varid'>handler</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>getUncaughtExceptionHandler</span>
<a name="line-26"></a>   <span class='hs-varid'>handler</span> <span class='hs-varid'>ex</span>
<a name="line-27"></a>
<a name="line-28"></a><span class='hs-comment'>-- SUP: Are the hooks allowed to re-enter Haskell land?  If so, remove</span>
<a name="line-29"></a><span class='hs-comment'>-- the unsafe below.</span>
<a name="line-30"></a><span class='hs-keyword'>foreign</span> <span class='hs-keyword'>import</span> <span class='hs-keyword'>ccall</span> <span class='hs-keyword'>unsafe</span> <span class='hs-str'>"stackOverflow"</span>
<a name="line-31"></a>        <span class='hs-varid'>callStackOverflowHook</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-32"></a>
<a name="line-33"></a><a name="uncaughtExceptionHandler"></a><span class='hs-comment'>{-# NOINLINE uncaughtExceptionHandler #-}</span>
<a name="line-34"></a><span class='hs-definition'>uncaughtExceptionHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>SomeException</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span>
<a name="line-35"></a><span class='hs-definition'>uncaughtExceptionHandler</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unsafePerformIO</span> <span class='hs-layout'>(</span><span class='hs-varid'>newIORef</span> <span class='hs-varid'>defaultHandler</span><span class='hs-layout'>)</span>
<a name="line-36"></a>   <span class='hs-keyword'>where</span>
<a name="line-37"></a>      <span class='hs-varid'>defaultHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>SomeException</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-38"></a>      <span class='hs-varid'>defaultHandler</span> <span class='hs-varid'>se</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>SomeException</span> <span class='hs-varid'>ex</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-39"></a>         <span class='hs-layout'>(</span><span class='hs-varid'>hFlush</span> <span class='hs-varid'>stdout</span><span class='hs-layout'>)</span> <span class='hs-varop'>`catchAny`</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span>
<a name="line-40"></a>         <span class='hs-keyword'>let</span> <span class='hs-varid'>msg</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>cast</span> <span class='hs-varid'>ex</span> <span class='hs-keyword'>of</span>
<a name="line-41"></a>               <span class='hs-conid'>Just</span> <span class='hs-conid'>Deadlock</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-str'>"no threads to run:  infinite loop or deadlock?"</span>
<a name="line-42"></a>               <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>cast</span> <span class='hs-varid'>ex</span> <span class='hs-keyword'>of</span>
<a name="line-43"></a>                    <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>ErrorCall</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>s</span>
<a name="line-44"></a>                    <span class='hs-keyword'>_</span>                  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>showsPrec</span> <span class='hs-num'>0</span> <span class='hs-varid'>se</span> <span class='hs-str'>""</span>
<a name="line-45"></a>         <span class='hs-varid'>withCString</span> <span class='hs-str'>"%s"</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>cfmt</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-46"></a>          <span class='hs-varid'>withCString</span> <span class='hs-varid'>msg</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>cmsg</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-47"></a>            <span class='hs-varid'>errorBelch</span> <span class='hs-varid'>cfmt</span> <span class='hs-varid'>cmsg</span>
<a name="line-48"></a>
<a name="line-49"></a><span class='hs-comment'>-- don't use errorBelch() directly, because we cannot call varargs functions</span>
<a name="line-50"></a><span class='hs-comment'>-- using the FFI.</span>
<a name="line-51"></a><span class='hs-keyword'>foreign</span> <span class='hs-keyword'>import</span> <span class='hs-keyword'>ccall</span> <span class='hs-keyword'>unsafe</span> <span class='hs-str'>"HsBase.h errorBelch2"</span>
<a name="line-52"></a>   <span class='hs-varid'>errorBelch</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>CString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>CString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-53"></a>
<a name="line-54"></a><a name="setUncaughtExceptionHandler"></a><span class='hs-definition'>setUncaughtExceptionHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>SomeException</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-55"></a><span class='hs-definition'>setUncaughtExceptionHandler</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>writeIORef</span> <span class='hs-varid'>uncaughtExceptionHandler</span>
<a name="line-56"></a>
<a name="line-57"></a><a name="getUncaughtExceptionHandler"></a><span class='hs-definition'>getUncaughtExceptionHandler</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>SomeException</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span>
<a name="line-58"></a><span class='hs-definition'>getUncaughtExceptionHandler</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>readIORef</span> <span class='hs-varid'>uncaughtExceptionHandler</span>
<a name="line-59"></a>
</pre>\end{code}
</body>
</html>