\section{Artificial Bottlenecks for Parallel Computation}
In the absence of a thread priority support for haskell, and the desire not to overwhelm the rendering thread with many nonessential modeling threads, we implement an artificial bottleneck that restricts at a very coarse level the number of parallel computations that may take place at any one time.
By claiming a bottleneck, we ensure that no other operation can run on that bottleneck until the bottleneck is released. This is essentially a semaphore, but the goal is related to performance rather than correctness.
\begin{code}
module RSAGL.Bottleneck
(constrict,newBottleneck,Bottleneck)
where
import Control.Monad
import Control.Concurrent.MVar
\end{code}
\begin{code}
newtype Bottleneck = Bottleneck (MVar ())
newBottleneck :: IO (Bottleneck)
newBottleneck = liftM Bottleneck $ newMVar ()
constrict :: Bottleneck -> IO a -> IO a
constrict bottleneck action =
do claim bottleneck
result <- action
release bottleneck
return result
claim :: Bottleneck -> IO ()
claim (Bottleneck mv) = takeMVar mv
release :: Bottleneck -> IO ()
release (Bottleneck mv) = putMVar mv ()
\end{code}