-- (c) The FFI task force, [2000..2001] -- -- Provides references to Haskell expressions that is guaranteed not to be -- affected by garbage collection, ie, it will neither be deallocated nor -- will the value of the stable pointer itself change during garbage -- collection (ordinary references may be relocated during garbage -- collection). Consequently, stable pointers can be passed to foreign code, -- which can handle it as an opaque reference to a Haskell value. module StablePtr ( StablePtr, -- data StablePtr a; instances: Eq newStablePtr, -- :: a -> IO (StablePtr a) deRefStablePtr, -- :: StablePtr a -> IO a freeStablePtr, -- :: StablePtr a -> IO () castStablePtrToPtr, -- :: StablePtr a -> Ptr () castPtrToStablePtr -- :: Ptr () -> StablePtr a ) where import Ptr (Ptr, castPtr) -- Pointer to a Haskell expression that is guaranteed not to be affect by -- garbage collection -- -- * concrete implementations may choose a different representation -- -- * In C land, values of type `StablePtr a' are represented by -- -- typedef void *HsStablePtr; -- newtype StablePtr a = StablePtr (Ptr a) deriving (Eq) -- Obtains a stable pointer for an arbitrary Haskell expression -- newStablePtr :: a -> IO (StablePtr a) newStablePtr v = do sp <- primNewStablePtr v return $ StablePtr sp -- Recovers the Haskell value refereed to by a stable pointer -- deRefStablePtr :: StablePtr a -> IO a deRefStablePtr (StablePtr sp) = do primDeRefStablePtr sp -- Dissolve the association between the stable pointer and the Haskell value -- -- * Afterwards, if the stable pointer is passed to `deRefStablePtr' or -- `freeStablePtr', the behaviour is undefined. However, the stable pointer -- may still be passed to `castStablePtrToPtr', but the `Ptr ()' value -- returned by `castStablePtrToPtr', in this case, is undefined (in -- particular, it may be `Ptr.nullPtr'). Nevertheless, the call is guaranteed -- not to diverge. -- freeStablePtr :: StablePtr a -> IO () freeStablePtr (StablePtr sp) = do primFreeStablePtr sp -- Coerces a stable pointer to vanilla pointer -- -- * No guarantees are made about the resulting value, except that the -- original stable pointer can be recovered by `castPtrToStablePtr'. In -- particular, the address may not refer to a valid memory address and any -- attempt to pass it to the member functions of the class `Storable' will -- most likely lead to disaster. -- -- * A pointer type parametrised with `()' is returned to indicate that no -- assumption may be made about the entity referenced by the pointer -- castStablePtrToPtr :: StablePtr a -> Ptr () castStablePtrToPtr (StablePtr sp) = castPtr sp -- Recover a stable pointer from its associated vanilla pointer value -- -- * We have -- -- sp == castPtrToStablePtr (castStablePtrToPtr sp) -- -- as long as `freeStablePtr' has not been executed on `sp' -- -- * The behaviour of `castPtrToStablePtr' is undefined for pointers not -- obtained by `castStablePtrToPtr' -- castPtrToStablePtr :: Ptr () -> StablePtr a castPtrToStablePtr p = castPtr p