{-# LANGUAGE UnicodeSyntax , NoImplicitPrelude , KindSignatures #-} ------------------------------------------------------------------------------- -- | -- Module : Foreign.Ptr.Region.Internal -- Copyright : (c) 2010 Bas van Dijk -- License : BSD3 (see the file LICENSE) -- Maintainer : Bas van Dijk -- ------------------------------------------------------------------------------- module Foreign.Ptr.Region.Internal ( -- * Regional pointers RegionalPtr(RegionalPtr) -- * Unsafely constructing regional pointers , unsafeRegionalPtr , unsafePureRegionalPtr -- * Unsafe utility functions for lifting operations on @Ptrs@ to @RegionalPtrs@ , unsafePtr , unsafeWrap, unsafeWrap2, unsafeWrap3 ) where -------------------------------------------------------------------------------- -- Imports -------------------------------------------------------------------------------- -- from base: import Control.Monad ( return, liftM ) import Data.Function ( ($) ) import Data.Maybe ( Maybe(Nothing, Just) ) import System.IO ( IO ) import Foreign.Ptr ( Ptr ) -- from base-unicode-symbols: import Data.Function.Unicode ( (∘) ) -- from transformers: import Control.Monad.IO.Class ( MonadIO, liftIO ) -- from regions: import Control.Monad.Trans.Region.OnExit ( FinalizerHandle, Finalizer, onExit ) import Control.Monad.Trans.Region ( RegionT, RootRegion, Dup(dup) ) -------------------------------------------------------------------------------- -- * Regional pointers -------------------------------------------------------------------------------- -- | A regional handle to memory. This should provide a safer replacement for -- @Foreign.Ptr.'Ptr'@ data RegionalPtr α (r ∷ * → *) = RegionalPtr !(Ptr α) !(Maybe (FinalizerHandle r)) instance Dup (RegionalPtr α) where dup (RegionalPtr ptr Nothing) = return $ RegionalPtr ptr Nothing dup (RegionalPtr ptr (Just ch)) = liftM (RegionalPtr ptr ∘ Just) $ dup ch -------------------------------------------------------------------------------- -- * Constructing regional pointers -------------------------------------------------------------------------------- -- | Construct a regional pointer from a native pointer -- and an @IO@ computation that finalizes the pointer (like @free ptr@) -- which is performed when the region terminates. -- -- This function is unsafe because this library can't guarantee that the -- finalizer will actually finalize the pointer (suppose having @return ()@ as -- the finalizer). You have to verify the correct finalisation yourself. unsafeRegionalPtr ∷ MonadIO pr ⇒ Ptr α → Finalizer → RegionT s pr (RegionalPtr α (RegionT s pr)) unsafeRegionalPtr ptr finalize = liftM (RegionalPtr ptr ∘ Just) $ onExit finalize -- | Construct a regional pointer from a native pointer -- without registering a finalizer like @free ptr@. -- -- This function is unsafe because this library can't guarantee the finalisation -- of the pointer, you have to verify the correct finalisation yourself. -- -- Note that the region parameter of the 'RegionalPtr' is set to 'RootRegion' -- which is the ancestor of any region. This allows the regional pointer to be -- used in any region. unsafePureRegionalPtr ∷ Ptr α → RegionalPtr α RootRegion unsafePureRegionalPtr ptr = RegionalPtr ptr Nothing -------------------------------------------------------------------------------- -- * Utility functions for lifting operations on Ptrs to RegionalPtrs -------------------------------------------------------------------------------- -- | Retrieve the native pointer from a regional pointer. -- -- This function is unsafe because it both allows you to @free@ the pointer -- before the region terminates and use the pointer outside the region when it -- is already freed. unsafePtr ∷ RegionalPtr α r → Ptr α unsafePtr (RegionalPtr ptr _) = ptr unsafeWrap ∷ MonadIO m ⇒ (Ptr α → IO β) → (RegionalPtr α r → m β) unsafeWrap f rPtr = liftIO $ f (unsafePtr rPtr) unsafeWrap2 ∷ MonadIO m ⇒ (Ptr α → γ → IO β) → (RegionalPtr α r → γ → m β) unsafeWrap2 f rPtr x = liftIO $ f (unsafePtr rPtr) x unsafeWrap3 ∷ MonadIO m ⇒ (Ptr α → γ → δ → IO β) → (RegionalPtr α r → γ → δ → m β) unsafeWrap3 f rPtr x y = liftIO $ f (unsafePtr rPtr) x y -- The End ---------------------------------------------------------------------