{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude #-} ------------------------------------------------------------------------------- -- | -- Module : Foreign.Ptr.Region -- Copyright : (c) 2010 Bas van Dijk -- License : BSD3 (see the file LICENSE) -- Maintainer : Bas van Dijk -- ------------------------------------------------------------------------------- module Foreign.Ptr.Region ( -- * Regional pointers RegionalPtr {-| Note that this module re-exports the @Control.Monad.Trans.Region@ module from the @regions@ package which allows you to: * Run a region using 'runRegionT'. * Concurrently run a region inside another region using 'forkTopRegion'. * Duplicate a 'RegionalPtr' to a parent region using 'dup'. -} , module Control.Monad.Trans.Region -- * Constructing regional pointers , regionalPtr , nullPtr -- * Pure functions on regional pointers , mapRegionalPtr , castPtr , plusPtr , alignPtr , minusPtr ) where -------------------------------------------------------------------------------- -- Imports -------------------------------------------------------------------------------- -- from base: import Control.Monad ( return, (>>=), fail ) import Data.Function ( ($) ) import Data.Int ( Int ) import Data.Maybe ( Maybe(Nothing, Just) ) import Foreign.Ptr ( Ptr ) import qualified Foreign.Ptr as FP ( nullPtr , castPtr, plusPtr, alignPtr, minusPtr ) -- from transformers: import Control.Monad.IO.Class ( MonadIO ) -- from regions: import Control.Monad.Trans.Region -- (re-exported entirely) import Control.Monad.Trans.Region.OnExit ( CloseAction, onExit ) -- from ourselves: import Foreign.Ptr.Region.Internal ( RegionalPtr(RegionalPtr) ) import Foreign.Ptr.Region.Unsafe ( unsafePtr ) -------------------------------------------------------------------------------- -- * Constructing regional pointers -------------------------------------------------------------------------------- -- | Construct a regional pointer from a native pointer and an @IO@ computation -- that frees the pointer which is executed when the region exits. regionalPtr ∷ MonadIO pr ⇒ Ptr α → CloseAction → RegionT s pr (RegionalPtr α (RegionT s pr)) regionalPtr ptr freePtr = do ch ← onExit freePtr return $ RegionalPtr ptr $ Just ch -- | The constant @nullPtr@ contains a distinguished value of 'RegionalPtr' -- that is not associated with a valid memory location. -- -- Note that @nullPtr@ is a pure value. This means it does not perform the -- side-effect of registering a 'CloseAction' like @free nullPtr@ in the -- 'RegionT' monad. nullPtr ∷ RegionalPtr α r nullPtr = RegionalPtr FP.nullPtr Nothing -------------------------------------------------------------------------------- -- * Pure functions on regional pointers -------------------------------------------------------------------------------- -- | Apply a /pure/ function to the inner pointer of a regional pointer. mapRegionalPtr ∷ (Ptr α → Ptr β) → (RegionalPtr α r → RegionalPtr β r) mapRegionalPtr f = \(RegionalPtr ptr ch) → RegionalPtr (f ptr) ch -- | The @castPtr@ function casts a pointer from one type to another. -- -- Wraps: @Foreign.Ptr.@'FP.castPtr' castPtr ∷ RegionalPtr α r → RegionalPtr β r castPtr = mapRegionalPtr FP.castPtr -- | Advances the given address by the given offset in bytes. -- -- Wraps: @Foreign.Ptr.@'FP.plusPtr' plusPtr ∷ RegionalPtr α r → Int → RegionalPtr β r plusPtr rp n = mapRegionalPtr (\p → FP.plusPtr p n) rp -- | Given an arbitrary address and an alignment constraint, @alignPtr@ yields -- the next higher address that fulfills the alignment constraint. An alignment -- constraint @x@ is fulfilled by any address divisible by @x@. This operation -- is idempotent. -- -- Wraps: @Foreign.Ptr.@'FP.alignPtr' alignPtr ∷ RegionalPtr α r → Int → RegionalPtr α r alignPtr rp n = mapRegionalPtr (\p → FP.alignPtr p n) rp -- | Computes the offset required to get from the second to the first -- argument. We have -- -- > p2 == p1 `plusPtr` (p2 `minusPtr` p1) -- -- Wraps: @Foreign.Ptr.@'FP.minusPtr' minusPtr ∷ RegionalPtr α r1 → RegionalPtr β r2 → Int minusPtr rp1 rp2 = FP.minusPtr (unsafePtr rp1) (unsafePtr rp2) -- The End ---------------------------------------------------------------------