--  Haskell Ports Library: single assignment variables
--
--  Author : Manuel M T Chakravarty
--  Created: 20 March 2000
--
--  Version $Revision: 1.4 $ from $Date: 2003/06/22 15:25:32 $
--
--  Copyright (c) [2000..2003] Manuel M T Chakravarty
--
--  This file is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation; either version 2 of the License, or
--  (at your option) any later version.
--
--  This file is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--- DESCRIPTION ---------------------------------------------------------------
--
--  Single assignment variables realised on top of `MVars'.
--
--- DOCU ----------------------------------------------------------------------
--
--  language: Haskell 98 + Concurrent + Exceptions
--
--- TODO ----------------------------------------------------------------------
--

module Control.Concurrent.SVars (V, newV, valV, (<<))
where

import Control.Monad	  (liftM, unless)

import System.IO.Unsafe	  (unsafePerformIO)
import Control.Concurrent (MVar, newEmptyMVar, putMVar, tryPutMVar, readMVar, takeMVar)


infix  3 <<

-- single assignment variable (EXPORTED ABSTRACTLY)
--
newtype V a = V (MVar a)

-- create a single assignment variable (EXPORTED)
--
newV :: IO (V a)
newV  = liftM V newEmptyMVar

-- access a single assignment variable's value (EXPORTED)
--
valV       :: V a -> a
{-# NOINLINE valV #-}
valV (V v)  = unsafePerformIO (readMVar v)

-- write into a single assignment variable (EXPORTED)
--
(<<)       :: V a -> a -> IO ()
(V v) << x  = do
	        success <- tryPutMVar v x
		unless success $
		  fail "(SVars.<<): Wrote to full single assignment variable"