packages feed

cash-0.1.0.0: src/Math/ComputerAlgebra/Cash/Monitor.hs

{-# OPTIONS_GHC -cpp #-}
{-# LANGUAGE ForeignFunctionInterface #-}
----------------------------------------------------------------------------
-- (c) 2010
--     Hans-Wolfgang Loidl <hwloidl@cs.st-andrews.ac.uk>
--  code clean-up and port to ghc-6.12.2
--  
-- (c) 2008
--     Jost Berthold <berthold@mathematik.uni-marburg.de>
--  introduced more accurate types and included header file
--  
--
-- (c) 2006
--     Abdallah Al Zain <ceeatia@macs.hw.ac.uk>
--     
-- this module is intended to bypass the heap, stack of an ordinary STG machine
-- provding an interface to an external repository, (hence a side-effect).
-----------------------------------------------------------------------------
module Math.ComputerAlgebra.Cash.Monitor where

import Foreign.StablePtr
import Foreign.Ptr -- for NULL pointer
 -- types only
import System.IO -- IO,Handle
import Control.Concurrent

#ifndef __PARALLEL_HASKELL__
-- version for testing with ghci, no C stuff involved
import System.IO.Unsafe
import Control.Monad

-- data is stored in CAF. We cannot do this in a parallel version,
-- because we cannot rely on per-PE execution.
{-# NOINLINE storageVar #-}
storageVar :: MVar (StablePtr (MVar a))
storageVar = unsafePerformIO (newEmptyMVar)

cwriteMVarPointer :: StablePtr (MVar a) -> IO()
cwriteMVarPointer ptr = do
  empty <- isEmptyMVar storageVar
  when (not empty) (takeMVar storageVar >> return ()) -- empty it
  putMVar storageVar ptr

cdeleteMVarPointer :: IO ()
cdeleteMVarPointer = do 
  empty <- isEmptyMVar storageVar
  if empty then return () 
           else do takeMVar storageVar
                   return ()

creadMVarPointer :: IO (StablePtr (MVar a))
creadMVarPointer = do 
  empty <- isEmptyMVar storageVar
  if empty then return (castPtrToStablePtr nullPtr)
           else readMVar storageVar

-- ID supply, hand-rolled.
{-# NOINLINE idVar #-}
idVar :: MVar Integer -- overflow impossible, but IDs may get very long!
idVar = unsafePerformIO (newMVar 0)

newID :: IO String
newID = do i <- takeMVar idVar
           putMVar idVar (i+1)
           return ("HsSCSCP" ++ show i)

#else

foreign import ccall  unsafe 
    "monitor.h cwriteMVarPointer" cwriteMVarPointer 
    :: StablePtr (MVar a) -> IO()
foreign import ccall unsafe 
    "monitor.h cdeleteMVarPointer" cdeleteMVarPointer 
    :: IO ()
foreign import ccall unsafe
    "monitor.h creadMVarPointer" creadMVarPointer 
    :: IO (StablePtr (MVar a))

foreign import ccall  unsafe 
    "monitor.h cwriteIDVarPointer" cwriteIDVarPointer 
    :: StablePtr (MVar Integer) -> IO()
foreign import ccall unsafe 
    "monitor.h cdeleteIDVarPointer" cdeleteIDVarPointer 
    :: IO ()
foreign import ccall unsafe
    "monitor.h creadIDVarPointer" creadIDVarPointer 
    :: IO (StablePtr (MVar Integer))

-- ID supply for PARALLEL_HASKELL
idInit :: IO (StablePtr (MVar Integer))
idInit = do v <- newMVar 0
            p <- newStablePtr v
            cwriteIDVarPointer p
            return p

-- will surely never be used...
idCancel :: IO ()
idCancel = cdeleteIDVarPointer

newID :: IO String
newID = do p <- creadIDVarPointer
           -- check if null, init if so
           let checkP = castStablePtrToPtr p
#warning   -- check for race condition
           p' <- if (checkP == nullPtr) then idInit 
                                        else return p
           idVar <- deRefStablePtr p
           i <- modifyMVar idVar ( \n  -> return (n+1,n)) 
                               -- take -> (put,return)
           return ("HsSCSCP" ++ show i)

#endif