packages feed

regional-pointers-0.1: Foreign/Ptr/Region/Internal.hs

{-# LANGUAGE UnicodeSyntax
           , NoImplicitPrelude
           , TypeFamilies
           , CPP
  #-}

-------------------------------------------------------------------------------
-- |
-- Module      :  Foreign.Ptr.Region.Internal
-- Copyright   :  (c) 2010 Bas van Dijk
-- License     :  BSD3 (see the file LICENSE)
-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>
--
-------------------------------------------------------------------------------

module Foreign.Ptr.Region.Internal
    ( -- * Memory as a scarce resource
      Memory(..)
    , RegionalPtr

      -- * Utility functions for lifting operations on Ptrs to RegionalPtrs
    , mapRegionalPtr
    , unsafePtr
    , unsafeWrap, unsafeWrap2, unsafeWrap3
    ) where


--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------

-- from base:
import Data.Function                          ( ($) )
import Data.Int                               ( Int )
import Control.Monad                          ( liftM )
import System.IO                              ( IO )
import Foreign.Ptr                            ( Ptr )
import qualified Foreign.Marshal.Alloc as FMA ( mallocBytes, free )

-- from base-unicode-symbols:
import Data.Function.Unicode                  ( (∘) )

-- from transformers:
import Control.Monad.Trans                    ( MonadIO, liftIO )

-- from regions:
import Control.Monad.Trans.Region             ( RegionalHandle )
import Control.Monad.Trans.Region.Unsafe      ( Resource
                                              , Handle
                                              , openResource
                                              , closeResource
                                              , internalHandle
                                              , mapInternalHandle
                                              )
#ifdef __HADDOCK__
import Control.Monad.Trans.Region ( open )
#endif


--------------------------------------------------------------------------------
-- Memory as a scarce resource
--------------------------------------------------------------------------------

{-| Represents memory of 'size' number of bytes which may be marshalled to or
from Haskell values of type @&#945;@. Before you can use the memory you have to
allocate it using 'open'.
-}
newtype Memory α = Memory { size ∷ Int }

instance Resource (Memory α) where
    newtype Handle (Memory α) = Pointer { ptr ∷ Ptr α }

    openResource  = liftM Pointer ∘ FMA.mallocBytes ∘ size
    closeResource = FMA.free ∘ ptr

-- | Handy type synonym for a regional handle to memory. This should provide a
-- safer replacement for @Foreign.Ptr.@'Ptr'
type RegionalPtr α r = RegionalHandle (Memory α) r


--------------------------------------------------------------------------------
-- Utility functions for lifting operations on Ptrs to RegionalPtrs
--------------------------------------------------------------------------------

mapRegionalPtr ∷ (Ptr α → Ptr β) → (RegionalPtr α r → RegionalPtr β r)
mapRegionalPtr f = mapInternalHandle $ Pointer ∘ f ∘ ptr

unsafePtr ∷ RegionalPtr α r → Ptr α
unsafePtr = ptr ∘ internalHandle

unsafeWrap ∷ MonadIO m
           ⇒ (Ptr α → IO β)
           → (RegionalPtr α r → m β)
unsafeWrap f rp = liftIO $ f $ unsafePtr rp

unsafeWrap2 ∷ MonadIO m
            ⇒ (Ptr α → γ → IO β)
            → (RegionalPtr α r → γ → m β)
unsafeWrap2 f rp x = liftIO $ f (unsafePtr rp) x

unsafeWrap3 ∷ MonadIO m
            ⇒ (Ptr α → γ → δ → IO β)
            → (RegionalPtr α r → γ → δ → m β)
unsafeWrap3 f rp x y = liftIO $ f (unsafePtr rp) x y


-- The End ---------------------------------------------------------------------