{-# LANGUAGE CPP
, UnicodeSyntax
, NoImplicitPrelude
, KindSignatures
, RankNTypes
#-}--------------------------------------------------------------------------------- |-- 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>---------------------------------------------------------------------------------moduleForeign.Ptr.Region.Internal(-- * Regional pointersRegionalPtr(RegionalPtr),unsafeRegionalPtr,wrapMalloc-- * Null pointers,nullPtr,NullPtr-- * Foreign regional pointers,LocalPtr,wrapAlloca,wrapAlloca2-- * Wrapping @CStringLen@ operations,wrapPeekStringLen,wrapNewStringLen,wrapWithStringLen-- * Unsafe utility functions for lifting operations on @Ptrs@ to @RegionalPtrs@,Pointer(unsafePtr,mapPointer),unsafeWrap,unsafeWrap2,unsafeWrap3,unsafeWrap2flp-- * Pointers to allocated memory,AllocatedPointer)where---------------------------------------------------------------------------------- Imports---------------------------------------------------------------------------------- from base:importControl.Monad(return,liftM)importControl.Arrow(first)importData.Function(($),flip)importData.Int(Int)importData.Char(String)importSystem.IO(IO)importForeign.Ptr(Ptr)importqualifiedForeign.PtrasFP(nullPtr)importForeign.Marshal.Alloc(free)#if __GLASGOW_HASKELL__ < 700importControl.Monad((>>=),fail)#endif-- from base-unicode-symbols:importData.Function.Unicode((∘))-- from transformers:importControl.Monad.IO.Class(MonadIO,liftIO)-- from regions:importControl.Monad.Trans.Region.OnExit(FinalizerHandle,Finalizer,onExit)importControl.Monad.Trans.Region(RegionT,AncestorRegion,RootRegion,LocalRegion,Local,Dup(dup))importControl.Monad.Trans.Region.Unsafe(unsafeStripLocal)-- from monad-control:importControl.Monad.IO.Control(MonadControlIO,controlIO,liftIOOp)#if MIN_VERSION_base(4,3,0)importControl.Exception.Control(mask_)#elseimportControl.Exception.Control(block)mask_∷MonadControlIOm⇒ma→mamask_=block#endif---------------------------------------------------------------------------------- * Regional pointers--------------------------------------------------------------------------------{-|
A regional pointer to memory.
This should provide a safer replacement for @Foreign.Ptr.'Ptr'@
-}dataRegionalPtrα(r∷*→*)=RegionalPtr!(Ptrα)!(FinalizerHandler)instanceDup(RegionalPtrα)wheredup(RegionalPtrptrch)=liftM(RegionalPtrptr)(dupch){-|
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∷MonadIOpr⇒Ptrα→Finalizer→RegionTspr(RegionalPtrα(RegionTspr))unsafeRegionalPtrptrfinalize=liftM(RegionalPtrptr)(onExitfinalize)wrapMalloc∷MonadControlIOpr⇒IO(Ptrα)→RegionTspr(RegionalPtrα(RegionTspr))wrapMallocdoMalloc=mask_$doptr←liftIOdoMallocunsafeRegionalPtrptr(freeptr)---------------------------------------------------------------------------------- * Null pointers--------------------------------------------------------------------------------{-|
The constant @nullPtr@ is a pointer which 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 finalizer like \"@free nullPtr@\"
in the 'RegionT' monad.
Finally note that the region parameter of the 'NullPtr' is set to
'RootRegion' which is the ancestor of any region.
This allows 'nullPtr' to be used in any region.
-}nullPtr∷NullPtrαRootRegionnullPtr=NullPtrFP.nullPtrnewtypeNullPtrα(r∷*→*)=NullPtr(Ptrα)---------------------------------------------------------------------------------- * Foreign regional pointers---------------------------------------------------------------------------------- | A regional pointer to memory which was locally allocated-- by one of the @alloca@-like functions.---- Note that a @LocalPtr@ can not be 'dup'licated to a parent region.newtypeLocalPtrα(r∷*→*)=LocalPtr(Ptrα)wrapAlloca∷MonadControlIOpr⇒((Ptrα→IO(RegionTsprβ))→IO(RegionTsprβ))→(∀sl.LocalPtrα(LocalRegionsls)→RegionT(Locals)prβ)→RegionTsprβwrapAllocadoAllocaf=liftIOOpdoAlloca$unsafeStripLocal∘f∘LocalPtrwrapAlloca2∷MonadControlIOpr⇒((γ→Ptrα→IO(RegionTsprβ))→IO(RegionTsprβ))→(∀sl.γ→LocalPtrα(LocalRegionsls)→RegionT(Locals)prβ)→RegionTsprβwrapAlloca2doAllocaf=controlIO$\runInIO→doAlloca$\s→runInIO∘unsafeStripLocal∘fs∘LocalPtr---------------------------------------------------------------------------------- * Wrapping @CStringLen@ operations--------------------------------------------------------------------------------wrapPeekStringLen∷(Pointerpointer,pr`AncestorRegion`cr,MonadIOcr)⇒((Ptrα,Int)→IOString)→(pointerαpr,Int)→crStringwrapPeekStringLenpeekStringLen=liftIO∘peekStringLen∘firstunsafePtrwrapNewStringLen∷MonadControlIOpr⇒IO(Ptrα,Int)→RegionTspr(RegionalPtrα(RegionTspr),Int)wrapNewStringLennewStringLen=mask_$do(ptr,len)←liftIOnewStringLenrPtr←unsafeRegionalPtrptr(freeptr)return(rPtr,len)wrapWithStringLen∷MonadControlIOpr⇒(((Ptrα,Int)→IO(RegionTsprβ))→IO(RegionTsprβ))→(∀sl.(LocalPtrα(LocalRegionsls),Int)→RegionT(Locals)prβ)→RegionTsprβwrapWithStringLenwithStringLenf=liftIOOpwithStringLen$unsafeStripLocal∘f∘firstLocalPtr---------------------------------------------------------------------------------- * Utility functions for lifting operations on Ptrs to RegionalPtrs--------------------------------------------------------------------------------classPointer(pointer∷*→(*→*)→*)where-- | Retrieve the native pointer from a regional pointer.---- This function is unsafe because it allows you to both @free@ the pointer-- before the region terminates and use the pointer outside the region when it-- is already freed.unsafePtr∷pointerαr→Ptrα-- | Apply a /pure/ function to the inner pointer of a regional pointer.mapPointer∷(Ptrα→Ptrβ)→(pointerαr→pointerβr)instancePointerRegionalPtrwhereunsafePtr(RegionalPtrptr_)=ptrmapPointerf(RegionalPtrptrch)=RegionalPtr(fptr)chinstancePointerNullPtrwhereunsafePtr(NullPtrptr)=ptrmapPointerf(NullPtrptr)=NullPtr(fptr)instancePointerLocalPtrwhereunsafePtr(LocalPtrptr)=ptrmapPointerf(LocalPtrptr)=LocalPtr(fptr)unsafeWrap∷(MonadIOm,Pointerpointer)⇒(Ptrα→IOβ)→(pointerαr→mβ)unsafeWrapfpointer=liftIO$f(unsafePtrpointer)unsafeWrap2∷(MonadIOm,Pointerpointer)⇒(Ptrα→γ→IOβ)→(pointerαr→γ→mβ)unsafeWrap2fpointerx=liftIO$f(unsafePtrpointer)xunsafeWrap3∷(MonadIOm,Pointerpointer)⇒(Ptrα→γ→δ→IOβ)→(pointerαr→γ→δ→mβ)unsafeWrap3fpointerxy=liftIO$f(unsafePtrpointer)xyunsafeWrap2flp∷(MonadIOm,Pointerpointer)⇒(γ→Ptrα→IOβ)→(γ→pointerαr→mβ)unsafeWrap2flp=flip∘unsafeWrap2∘flip---------------------------------------------------------------------------------- * Allocated pointers--------------------------------------------------------------------------------classPointerpointer⇒PrivateAllocatedPointerpointer-- | Class of pointers which point to allocated memory. 'NullPtr' is the only-- pointer which is not an instance of this class.---- The super class 'PrivateAllocatedPointer' is not exported by this module-- which ensures you can't accidentally make 'NullPtr' an instance of this class.classPrivateAllocatedPointerpointer⇒AllocatedPointerpointerinstancePrivateAllocatedPointerRegionalPtr;instanceAllocatedPointerRegionalPtrinstancePrivateAllocatedPointerLocalPtr;instanceAllocatedPointerLocalPtr-- The End ---------------------------------------------------------------------