<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ --> <title>GHC/ForeignPtr.hs</title> <link type='text/css' rel='stylesheet' href='hscolour.css' /> </head> <body> <pre><a name="line-1"></a><span class='hs-comment'>{-# OPTIONS_GHC -XNoImplicitPrelude #-}</span> <a name="line-2"></a><span class='hs-comment'>{-# OPTIONS_HADDOCK hide #-}</span> <a name="line-3"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span> <a name="line-4"></a><span class='hs-comment'>-- |</span> <a name="line-5"></a><span class='hs-comment'>-- Module : GHC.ForeignPtr</span> <a name="line-6"></a><span class='hs-comment'>-- Copyright : (c) The University of Glasgow, 1992-2003</span> <a name="line-7"></a><span class='hs-comment'>-- License : see libraries/base/LICENSE</span> <a name="line-8"></a><span class='hs-comment'>-- </span> <a name="line-9"></a><span class='hs-comment'>-- Maintainer : cvs-ghc@haskell.org</span> <a name="line-10"></a><span class='hs-comment'>-- Stability : internal</span> <a name="line-11"></a><span class='hs-comment'>-- Portability : non-portable (GHC extensions)</span> <a name="line-12"></a><span class='hs-comment'>--</span> <a name="line-13"></a><span class='hs-comment'>-- GHC's implementation of the 'ForeignPtr' data type.</span> <a name="line-14"></a><span class='hs-comment'>-- </span> <a name="line-15"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span> <a name="line-16"></a> <a name="line-17"></a><span class='hs-comment'>-- #hide</span> <a name="line-18"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>ForeignPtr</span> <a name="line-19"></a> <span class='hs-layout'>(</span> <a name="line-20"></a> <span class='hs-conid'>ForeignPtr</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <a name="line-21"></a> <span class='hs-conid'>FinalizerPtr</span><span class='hs-layout'>,</span> <a name="line-22"></a> <span class='hs-conid'>FinalizerEnvPtr</span><span class='hs-layout'>,</span> <a name="line-23"></a> <span class='hs-varid'>newForeignPtr_</span><span class='hs-layout'>,</span> <a name="line-24"></a> <span class='hs-varid'>mallocForeignPtr</span><span class='hs-layout'>,</span> <a name="line-25"></a> <span class='hs-varid'>mallocPlainForeignPtr</span><span class='hs-layout'>,</span> <a name="line-26"></a> <span class='hs-varid'>mallocForeignPtrBytes</span><span class='hs-layout'>,</span> <a name="line-27"></a> <span class='hs-varid'>mallocPlainForeignPtrBytes</span><span class='hs-layout'>,</span> <a name="line-28"></a> <span class='hs-varid'>addForeignPtrFinalizer</span><span class='hs-layout'>,</span> <a name="line-29"></a> <span class='hs-varid'>addForeignPtrFinalizerEnv</span><span class='hs-layout'>,</span> <a name="line-30"></a> <span class='hs-varid'>touchForeignPtr</span><span class='hs-layout'>,</span> <a name="line-31"></a> <span class='hs-varid'>unsafeForeignPtrToPtr</span><span class='hs-layout'>,</span> <a name="line-32"></a> <span class='hs-varid'>castForeignPtr</span><span class='hs-layout'>,</span> <a name="line-33"></a> <span class='hs-varid'>newConcForeignPtr</span><span class='hs-layout'>,</span> <a name="line-34"></a> <span class='hs-varid'>addForeignPtrConcFinalizer</span><span class='hs-layout'>,</span> <a name="line-35"></a> <span class='hs-varid'>finalizeForeignPtr</span> <a name="line-36"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-37"></a> <a name="line-38"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span> <span class='hs-layout'>(</span> <span class='hs-varid'>sequence_</span> <span class='hs-layout'>)</span> <a name="line-39"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Storable</span> <a name="line-40"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Typeable</span> <a name="line-41"></a> <a name="line-42"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Show</span> <a name="line-43"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span> <span class='hs-layout'>(</span> <span class='hs-varid'>null</span> <span class='hs-layout'>)</span> <a name="line-44"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Base</span> <a name="line-45"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IORef</span> <a name="line-46"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>STRef</span> <span class='hs-layout'>(</span> <span class='hs-conid'>STRef</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span> <span class='hs-layout'>)</span> <a name="line-47"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Ptr</span> <span class='hs-layout'>(</span> <span class='hs-conid'>Ptr</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-conid'>FunPtr</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span> <span class='hs-layout'>)</span> <a name="line-48"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Err</span> <a name="line-49"></a> <a name="line-50"></a><span class='hs-cpp'>#include "Typeable.h"</span> <a name="line-51"></a> <a name="line-52"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- |The type 'ForeignPtr' represents references to objects that are</span> <a name="line-53"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- maintained in a foreign language, i.e., that are not part of the</span> <a name="line-54"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- data structures usually managed by the Haskell storage manager.</span> <a name="line-55"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- The essential difference between 'ForeignPtr's and vanilla memory</span> <a name="line-56"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- references of type @Ptr a@ is that the former may be associated</span> <a name="line-57"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- with /finalizers/. A finalizer is a routine that is invoked when</span> <a name="line-58"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- the Haskell storage manager detects that - within the Haskell heap</span> <a name="line-59"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- and stack - there are no more references left that are pointing to</span> <a name="line-60"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- the 'ForeignPtr'. Typically, the finalizer will, then, invoke</span> <a name="line-61"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- routines in the foreign language that free the resources bound by</span> <a name="line-62"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- the foreign object.</span> <a name="line-63"></a><a name="ForeignPtr"></a><span class='hs-comment'>--</span> <a name="line-64"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- The 'ForeignPtr' is parameterised in the same way as 'Ptr'. The</span> <a name="line-65"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- type argument of 'ForeignPtr' should normally be an instance of</span> <a name="line-66"></a><a name="ForeignPtr"></a><span class='hs-comment'>-- class 'Storable'.</span> <a name="line-67"></a><a name="ForeignPtr"></a><span class='hs-comment'>--</span> <a name="line-68"></a><a name="ForeignPtr"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-conid'>Addr</span><span class='hs-cpp'>#</span> <span class='hs-conid'>ForeignPtrContents</span> <a name="line-69"></a> <span class='hs-comment'>-- we cache the Addr# in the ForeignPtr object, but attach</span> <a name="line-70"></a> <span class='hs-comment'>-- the finalizer to the IORef (or the MutableByteArray# in</span> <a name="line-71"></a> <span class='hs-comment'>-- the case of a MallocPtr). The aim of the representation</span> <a name="line-72"></a> <span class='hs-comment'>-- is to make withForeignPtr efficient; in fact, withForeignPtr</span> <a name="line-73"></a> <span class='hs-comment'>-- should be just as efficient as unpacking a Ptr, and multiple</span> <a name="line-74"></a> <span class='hs-comment'>-- withForeignPtrs can share an unpacked ForeignPtr. Note</span> <a name="line-75"></a> <span class='hs-comment'>-- that touchForeignPtr only has to touch the ForeignPtrContents</span> <a name="line-76"></a> <span class='hs-comment'>-- object, because that ensures that whatever the finalizer is</span> <a name="line-77"></a> <span class='hs-comment'>-- attached to is kept alive.</span> <a name="line-78"></a> <a name="line-79"></a><span class='hs-conid'>INSTANCE_TYPEABLE1</span><span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span><span class='hs-layout'>,</span><span class='hs-varid'>foreignPtrTc</span><span class='hs-layout'>,</span><span class='hs-str'>"ForeignPtr"</span><span class='hs-layout'>)</span> <a name="line-80"></a> <a name="line-81"></a><a name="Finalizers"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Finalizers</span> <a name="line-82"></a> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>NoFinalizers</span> <a name="line-83"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>CFinalizers</span> <a name="line-84"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>HaskellFinalizers</span> <a name="line-85"></a> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Eq</span> <a name="line-86"></a> <a name="line-87"></a><a name="ForeignPtrContents"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>ForeignPtrContents</span> <a name="line-88"></a> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>PlainForeignPtr</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>Finalizers</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-89"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>MallocPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>MutableByteArray</span><span class='hs-cpp'>#</span> <span class='hs-conid'>RealWorld</span><span class='hs-layout'>)</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>Finalizers</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-90"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>PlainPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>MutableByteArray</span><span class='hs-cpp'>#</span> <span class='hs-conid'>RealWorld</span><span class='hs-layout'>)</span> <a name="line-91"></a> <a name="line-92"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Eq</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-93"></a> <span class='hs-varid'>p</span> <span class='hs-varop'>==</span> <span class='hs-varid'>q</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unsafeForeignPtrToPtr</span> <span class='hs-varid'>p</span> <span class='hs-varop'>==</span> <span class='hs-varid'>unsafeForeignPtrToPtr</span> <span class='hs-varid'>q</span> <a name="line-94"></a> <a name="line-95"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Ord</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-96"></a> <span class='hs-varid'>compare</span> <span class='hs-varid'>p</span> <span class='hs-varid'>q</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>compare</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeForeignPtrToPtr</span> <span class='hs-varid'>p</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeForeignPtrToPtr</span> <span class='hs-varid'>q</span><span class='hs-layout'>)</span> <a name="line-97"></a> <a name="line-98"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Show</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-99"></a> <span class='hs-varid'>showsPrec</span> <span class='hs-varid'>p</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>showsPrec</span> <span class='hs-varid'>p</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeForeignPtrToPtr</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <a name="line-100"></a> <a name="line-101"></a> <a name="line-102"></a><a name="FinalizerPtr"></a><span class='hs-comment'>-- |A finalizer is represented as a pointer to a foreign function that, at</span> <a name="line-103"></a><a name="FinalizerPtr"></a><span class='hs-comment'>-- finalisation time, gets as an argument a plain pointer variant of the</span> <a name="line-104"></a><a name="FinalizerPtr"></a><span class='hs-comment'>-- foreign pointer that the finalizer is associated with.</span> <a name="line-105"></a><a name="FinalizerPtr"></a><span class='hs-comment'>-- </span> <a name="line-106"></a><a name="FinalizerPtr"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>FinalizerPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FunPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <a name="line-107"></a><a name="FinalizerEnvPtr"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>FinalizerEnvPtr</span> <span class='hs-varid'>env</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FunPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span> <span class='hs-varid'>env</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <a name="line-108"></a> <a name="line-109"></a><a name="newConcForeignPtr"></a><span class='hs-definition'>newConcForeignPtr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <a name="line-110"></a><span class='hs-comment'>--</span> <a name="line-111"></a><span class='hs-comment'>-- ^Turns a plain memory reference into a foreign object by</span> <a name="line-112"></a><span class='hs-comment'>-- associating a finalizer - given by the monadic operation - with the</span> <a name="line-113"></a><span class='hs-comment'>-- reference. The storage manager will start the finalizer, in a</span> <a name="line-114"></a><span class='hs-comment'>-- separate thread, some time after the last reference to the</span> <a name="line-115"></a><span class='hs-comment'>-- @ForeignPtr@ is dropped. There is no guarantee of promptness, and</span> <a name="line-116"></a><span class='hs-comment'>-- in fact there is no guarantee that the finalizer will eventually</span> <a name="line-117"></a><span class='hs-comment'>-- run at all.</span> <a name="line-118"></a><span class='hs-comment'>--</span> <a name="line-119"></a><span class='hs-comment'>-- Note that references from a finalizer do not necessarily prevent</span> <a name="line-120"></a><span class='hs-comment'>-- another object from being finalized. If A's finalizer refers to B</span> <a name="line-121"></a><span class='hs-comment'>-- (perhaps using 'touchForeignPtr', then the only guarantee is that</span> <a name="line-122"></a><span class='hs-comment'>-- B's finalizer will never be started before A's. If both A and B</span> <a name="line-123"></a><span class='hs-comment'>-- are unreachable, then both finalizers will start together. See</span> <a name="line-124"></a><span class='hs-comment'>-- 'touchForeignPtr' for more on finalizer ordering.</span> <a name="line-125"></a><span class='hs-comment'>--</span> <a name="line-126"></a><span class='hs-definition'>newConcForeignPtr</span> <span class='hs-varid'>p</span> <span class='hs-varid'>finalizer</span> <a name="line-127"></a> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>fObj</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newForeignPtr_</span> <span class='hs-varid'>p</span> <a name="line-128"></a> <span class='hs-varid'>addForeignPtrConcFinalizer</span> <span class='hs-varid'>fObj</span> <span class='hs-varid'>finalizer</span> <a name="line-129"></a> <span class='hs-varid'>return</span> <span class='hs-varid'>fObj</span> <a name="line-130"></a> <a name="line-131"></a><a name="mallocForeignPtr"></a><span class='hs-definition'>mallocForeignPtr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Storable</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <a name="line-132"></a><span class='hs-comment'>-- ^ Allocate some memory and return a 'ForeignPtr' to it. The memory</span> <a name="line-133"></a><span class='hs-comment'>-- will be released automatically when the 'ForeignPtr' is discarded.</span> <a name="line-134"></a><span class='hs-comment'>--</span> <a name="line-135"></a><span class='hs-comment'>-- 'mallocForeignPtr' is equivalent to</span> <a name="line-136"></a><span class='hs-comment'>--</span> <a name="line-137"></a><span class='hs-comment'>-- > do { p <- malloc; newForeignPtr finalizerFree p }</span> <a name="line-138"></a><span class='hs-comment'>-- </span> <a name="line-139"></a><span class='hs-comment'>-- although it may be implemented differently internally: you may not</span> <a name="line-140"></a><span class='hs-comment'>-- assume that the memory returned by 'mallocForeignPtr' has been</span> <a name="line-141"></a><span class='hs-comment'>-- allocated with 'Foreign.Marshal.Alloc.malloc'.</span> <a name="line-142"></a><span class='hs-comment'>--</span> <a name="line-143"></a><span class='hs-comment'>-- GHC notes: 'mallocForeignPtr' has a heavily optimised</span> <a name="line-144"></a><span class='hs-comment'>-- implementation in GHC. It uses pinned memory in the garbage</span> <a name="line-145"></a><span class='hs-comment'>-- collected heap, so the 'ForeignPtr' does not require a finalizer to</span> <a name="line-146"></a><span class='hs-comment'>-- free the memory. Use of 'mallocForeignPtr' and associated</span> <a name="line-147"></a><span class='hs-comment'>-- functions is strongly recommended in preference to 'newForeignPtr'</span> <a name="line-148"></a><span class='hs-comment'>-- with a finalizer.</span> <a name="line-149"></a><span class='hs-comment'>-- </span> <a name="line-150"></a><span class='hs-definition'>mallocForeignPtr</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>doMalloc</span> <span class='hs-varid'>undefined</span> <a name="line-151"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>doMalloc</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Storable</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=></span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <a name="line-152"></a> <span class='hs-varid'>doMalloc</span> <span class='hs-varid'>a</span> <a name="line-153"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span> <span class='hs-varop'><</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>error</span> <span class='hs-str'>"mallocForeignPtr: size must be >= 0"</span> <a name="line-154"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-155"></a> <span class='hs-varid'>r</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newIORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>NoFinalizers</span><span class='hs-layout'>,</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span> <a name="line-156"></a> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-157"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>newAlignedPinnedByteArray</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span> <span class='hs-varid'>align</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-158"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>byteArrayContents</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeCoerce</span><span class='hs-cpp'>#</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-159"></a> <span class='hs-layout'>(</span><span class='hs-conid'>MallocPtr</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-160"></a> <span class='hs-layout'>}</span> <a name="line-161"></a> <span class='hs-keyword'>where</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sizeOf</span> <span class='hs-varid'>a</span> <a name="line-162"></a> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>align</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>alignment</span> <span class='hs-varid'>a</span> <a name="line-163"></a> <a name="line-164"></a><a name="mallocForeignPtrBytes"></a><span class='hs-comment'>-- | This function is similar to 'mallocForeignPtr', except that the</span> <a name="line-165"></a><span class='hs-comment'>-- size of the memory required is given explicitly as a number of bytes.</span> <a name="line-166"></a><span class='hs-definition'>mallocForeignPtrBytes</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <a name="line-167"></a><span class='hs-definition'>mallocForeignPtrBytes</span> <span class='hs-varid'>size</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>size</span> <span class='hs-varop'><</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>=</span> <a name="line-168"></a> <span class='hs-varid'>error</span> <span class='hs-str'>"mallocForeignPtrBytes: size must be >= 0"</span> <a name="line-169"></a><span class='hs-definition'>mallocForeignPtrBytes</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-170"></a> <span class='hs-varid'>r</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newIORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>NoFinalizers</span><span class='hs-layout'>,</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span> <a name="line-171"></a> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-172"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>newPinnedByteArray</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-173"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>byteArrayContents</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeCoerce</span><span class='hs-cpp'>#</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-174"></a> <span class='hs-layout'>(</span><span class='hs-conid'>MallocPtr</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-175"></a> <span class='hs-layout'>}</span> <a name="line-176"></a> <a name="line-177"></a><a name="mallocPlainForeignPtr"></a><span class='hs-comment'>-- | Allocate some memory and return a 'ForeignPtr' to it. The memory</span> <a name="line-178"></a><span class='hs-comment'>-- will be released automatically when the 'ForeignPtr' is discarded.</span> <a name="line-179"></a><span class='hs-comment'>--</span> <a name="line-180"></a><span class='hs-comment'>-- GHC notes: 'mallocPlainForeignPtr' has a heavily optimised</span> <a name="line-181"></a><span class='hs-comment'>-- implementation in GHC. It uses pinned memory in the garbage</span> <a name="line-182"></a><span class='hs-comment'>-- collected heap, as for mallocForeignPtr. Unlike mallocForeignPtr, a</span> <a name="line-183"></a><span class='hs-comment'>-- ForeignPtr created with mallocPlainForeignPtr carries no finalizers.</span> <a name="line-184"></a><span class='hs-comment'>-- It is not possible to add a finalizer to a ForeignPtr created with</span> <a name="line-185"></a><span class='hs-comment'>-- mallocPlainForeignPtr. This is useful for ForeignPtrs that will live</span> <a name="line-186"></a><span class='hs-comment'>-- only inside Haskell (such as those created for packed strings).</span> <a name="line-187"></a><span class='hs-comment'>-- Attempts to add a finalizer to a ForeignPtr created this way, or to</span> <a name="line-188"></a><span class='hs-comment'>-- finalize such a pointer, will throw an exception.</span> <a name="line-189"></a><span class='hs-comment'>-- </span> <a name="line-190"></a><span class='hs-definition'>mallocPlainForeignPtr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Storable</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <a name="line-191"></a><span class='hs-definition'>mallocPlainForeignPtr</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>doMalloc</span> <span class='hs-varid'>undefined</span> <a name="line-192"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>doMalloc</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Storable</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=></span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <a name="line-193"></a> <span class='hs-varid'>doMalloc</span> <span class='hs-varid'>a</span> <a name="line-194"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span> <span class='hs-varop'><</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>error</span> <span class='hs-str'>"mallocForeignPtr: size must be >= 0"</span> <a name="line-195"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-196"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>newAlignedPinnedByteArray</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span> <span class='hs-varid'>align</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-197"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>byteArrayContents</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeCoerce</span><span class='hs-cpp'>#</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-198"></a> <span class='hs-layout'>(</span><span class='hs-conid'>PlainPtr</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-199"></a> <span class='hs-layout'>}</span> <a name="line-200"></a> <span class='hs-keyword'>where</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sizeOf</span> <span class='hs-varid'>a</span> <a name="line-201"></a> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>align</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>alignment</span> <span class='hs-varid'>a</span> <a name="line-202"></a> <a name="line-203"></a><a name="mallocPlainForeignPtrBytes"></a><span class='hs-comment'>-- | This function is similar to 'mallocForeignPtrBytes', except that</span> <a name="line-204"></a><span class='hs-comment'>-- the internally an optimised ForeignPtr representation with no</span> <a name="line-205"></a><span class='hs-comment'>-- finalizer is used. Attempts to add a finalizer will cause an</span> <a name="line-206"></a><span class='hs-comment'>-- exception to be thrown.</span> <a name="line-207"></a><span class='hs-definition'>mallocPlainForeignPtrBytes</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <a name="line-208"></a><span class='hs-definition'>mallocPlainForeignPtrBytes</span> <span class='hs-varid'>size</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>size</span> <span class='hs-varop'><</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>=</span> <a name="line-209"></a> <span class='hs-varid'>error</span> <span class='hs-str'>"mallocPlainForeignPtrBytes: size must be >= 0"</span> <a name="line-210"></a><span class='hs-definition'>mallocPlainForeignPtrBytes</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-211"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>newPinnedByteArray</span><span class='hs-cpp'>#</span> <span class='hs-varid'>size</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-212"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>byteArrayContents</span><span class='hs-cpp'>#</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeCoerce</span><span class='hs-cpp'>#</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-213"></a> <span class='hs-layout'>(</span><span class='hs-conid'>PlainPtr</span> <span class='hs-varid'>mbarr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-214"></a> <span class='hs-layout'>}</span> <a name="line-215"></a> <a name="line-216"></a><a name="addForeignPtrFinalizer"></a><span class='hs-definition'>addForeignPtrFinalizer</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FinalizerPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-217"></a><span class='hs-comment'>-- ^This function adds a finalizer to the given foreign object. The</span> <a name="line-218"></a><span class='hs-comment'>-- finalizer will run /before/ all other finalizers for the same</span> <a name="line-219"></a><span class='hs-comment'>-- object which have already been registered.</span> <a name="line-220"></a><span class='hs-definition'>addForeignPtrFinalizer</span> <span class='hs-layout'>(</span><span class='hs-conid'>FunPtr</span> <span class='hs-varid'>fp</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>p</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>c</span> <span class='hs-keyword'>of</span> <a name="line-221"></a> <span class='hs-conid'>PlainForeignPtr</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>>></span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <a name="line-222"></a> <span class='hs-conid'>MallocPtr</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>>></span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <a name="line-223"></a> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>error</span> <span class='hs-str'>"GHC.ForeignPtr: attempt to add a finalizer to a plain pointer"</span> <a name="line-224"></a> <span class='hs-keyword'>where</span> <a name="line-225"></a> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <a name="line-226"></a> <span class='hs-varid'>noMixing</span> <span class='hs-conid'>CFinalizers</span> <span class='hs-varid'>r</span> <span class='hs-varop'>$</span> <a name="line-227"></a> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-228"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>r</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>STRef</span> <span class='hs-varid'>r</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-229"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>mkWeakForeignEnv</span><span class='hs-cpp'>#</span> <span class='hs-varid'>r</span><span class='hs-cpp'>#</span> <span class='hs-conid'>()</span> <span class='hs-varid'>fp</span> <span class='hs-varid'>p</span> <span class='hs-num'>0</span><span class='hs-cpp'>#</span> <span class='hs-varid'>nullAddr</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-varid'>w</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-230"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-varid'>finalizeForeign</span> <span class='hs-varid'>w</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span> <a name="line-231"></a> <a name="line-232"></a><a name="addForeignPtrFinalizerEnv"></a><span class='hs-definition'>addForeignPtrFinalizerEnv</span> <span class='hs-keyglyph'>::</span> <a name="line-233"></a> <span class='hs-conid'>FinalizerEnvPtr</span> <span class='hs-varid'>env</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>env</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-234"></a><span class='hs-comment'>-- ^ Like 'addForeignPtrFinalizerEnv' but allows the finalizer to be</span> <a name="line-235"></a><span class='hs-comment'>-- passed an additional environment parameter to be passed to the</span> <a name="line-236"></a><span class='hs-comment'>-- finalizer. The environment passed to the finalizer is fixed by the</span> <a name="line-237"></a><span class='hs-comment'>-- second argument to 'addForeignPtrFinalizerEnv'</span> <a name="line-238"></a><span class='hs-definition'>addForeignPtrFinalizerEnv</span> <span class='hs-layout'>(</span><span class='hs-conid'>FunPtr</span> <span class='hs-varid'>fp</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span> <span class='hs-varid'>ep</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>p</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>c</span> <span class='hs-keyword'>of</span> <a name="line-239"></a> <span class='hs-conid'>PlainForeignPtr</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>>></span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <a name="line-240"></a> <span class='hs-conid'>MallocPtr</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>>></span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <a name="line-241"></a> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>error</span> <span class='hs-str'>"GHC.ForeignPtr: attempt to add a finalizer to a plain pointer"</span> <a name="line-242"></a> <span class='hs-keyword'>where</span> <a name="line-243"></a> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <a name="line-244"></a> <span class='hs-varid'>noMixing</span> <span class='hs-conid'>CFinalizers</span> <span class='hs-varid'>r</span> <span class='hs-varop'>$</span> <a name="line-245"></a> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-246"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>r</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>STRef</span> <span class='hs-varid'>r</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-247"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>mkWeakForeignEnv</span><span class='hs-cpp'>#</span> <span class='hs-varid'>r</span><span class='hs-cpp'>#</span> <span class='hs-conid'>()</span> <span class='hs-varid'>fp</span> <span class='hs-varid'>p</span> <span class='hs-num'>1</span><span class='hs-cpp'>#</span> <span class='hs-varid'>ep</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-varid'>w</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-248"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-varid'>finalizeForeign</span> <span class='hs-varid'>w</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span> <a name="line-249"></a> <a name="line-250"></a><a name="finalizeForeign"></a><span class='hs-definition'>finalizeForeign</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Weak</span><span class='hs-cpp'>#</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-251"></a><span class='hs-definition'>finalizeForeign</span> <span class='hs-varid'>w</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-252"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>finalizeWeak</span><span class='hs-cpp'>#</span> <span class='hs-varid'>w</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <a name="line-253"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-num'>0</span><span class='hs-cpp'>#</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-254"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>,</span> <span class='hs-varid'>f</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>f</span> <span class='hs-varid'>s1</span> <a name="line-255"></a> <a name="line-256"></a><a name="addForeignPtrConcFinalizer"></a><span class='hs-definition'>addForeignPtrConcFinalizer</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-257"></a><span class='hs-comment'>-- ^This function adds a finalizer to the given @ForeignPtr@. The</span> <a name="line-258"></a><span class='hs-comment'>-- finalizer will run /before/ all other finalizers for the same</span> <a name="line-259"></a><span class='hs-comment'>-- object which have already been registered.</span> <a name="line-260"></a><span class='hs-comment'>--</span> <a name="line-261"></a><span class='hs-comment'>-- This is a variant of @addForeignPtrFinalizer@, where the finalizer</span> <a name="line-262"></a><span class='hs-comment'>-- is an arbitrary @IO@ action. When it is invoked, the finalizer</span> <a name="line-263"></a><span class='hs-comment'>-- will run in a new thread.</span> <a name="line-264"></a><span class='hs-comment'>--</span> <a name="line-265"></a><span class='hs-comment'>-- NB. Be very careful with these finalizers. One common trap is that</span> <a name="line-266"></a><span class='hs-comment'>-- if a finalizer references another finalized value, it does not</span> <a name="line-267"></a><span class='hs-comment'>-- prevent that value from being finalized. In particular, 'Handle's</span> <a name="line-268"></a><span class='hs-comment'>-- are finalized objects, so a finalizer should not refer to a 'Handle'</span> <a name="line-269"></a><span class='hs-comment'>-- (including @stdout@, @stdin@ or @stderr@).</span> <a name="line-270"></a><span class='hs-comment'>--</span> <a name="line-271"></a><span class='hs-definition'>addForeignPtrConcFinalizer</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-varid'>finalizer</span> <span class='hs-keyglyph'>=</span> <a name="line-272"></a> <span class='hs-varid'>addForeignPtrConcFinalizer_</span> <span class='hs-varid'>c</span> <span class='hs-varid'>finalizer</span> <a name="line-273"></a> <a name="line-274"></a><a name="addForeignPtrConcFinalizer_"></a><span class='hs-definition'>addForeignPtrConcFinalizer_</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ForeignPtrContents</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-275"></a><span class='hs-definition'>addForeignPtrConcFinalizer_</span> <span class='hs-layout'>(</span><span class='hs-conid'>PlainForeignPtr</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varid'>finalizer</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-276"></a> <span class='hs-varid'>noFinalizers</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>noMixing</span> <span class='hs-conid'>HaskellFinalizers</span> <span class='hs-varid'>r</span> <span class='hs-layout'>(</span><span class='hs-varid'>return</span> <span class='hs-varid'>finalizer</span><span class='hs-layout'>)</span> <a name="line-277"></a> <span class='hs-keyword'>if</span> <span class='hs-varid'>noFinalizers</span> <a name="line-278"></a> <span class='hs-keyword'>then</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-279"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>r</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>STRef</span> <span class='hs-varid'>r</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-280"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>mkWeak</span><span class='hs-cpp'>#</span> <span class='hs-varid'>r</span><span class='hs-cpp'>#</span> <span class='hs-conid'>()</span> <span class='hs-layout'>(</span><span class='hs-varid'>foreignPtrFinalizer</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <a name="line-281"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span> <a name="line-282"></a> <span class='hs-keyword'>else</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <a name="line-283"></a><span class='hs-definition'>addForeignPtrConcFinalizer_</span> <span class='hs-varid'>f</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>MallocPtr</span> <span class='hs-varid'>fo</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varid'>finalizer</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-284"></a> <span class='hs-varid'>noFinalizers</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>noMixing</span> <span class='hs-conid'>HaskellFinalizers</span> <span class='hs-varid'>r</span> <span class='hs-layout'>(</span><span class='hs-varid'>return</span> <span class='hs-varid'>finalizer</span><span class='hs-layout'>)</span> <a name="line-285"></a> <span class='hs-keyword'>if</span> <span class='hs-varid'>noFinalizers</span> <a name="line-286"></a> <span class='hs-keyword'>then</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <a name="line-287"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>mkWeak</span><span class='hs-cpp'>#</span> <span class='hs-varid'>fo</span> <span class='hs-conid'>()</span> <span class='hs-layout'>(</span><span class='hs-keyword'>do</span> <span class='hs-varid'>foreignPtrFinalizer</span> <span class='hs-varid'>r</span><span class='hs-layout'>;</span> <span class='hs-varid'>touch</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <a name="line-288"></a> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s1</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-289"></a> <span class='hs-keyword'>else</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <a name="line-290"></a> <a name="line-291"></a><span class='hs-definition'>addForeignPtrConcFinalizer_</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <a name="line-292"></a> <span class='hs-varid'>error</span> <span class='hs-str'>"GHC.ForeignPtr: attempt to add a finalizer to plain pointer"</span> <a name="line-293"></a> <a name="line-294"></a><a name="noMixing"></a><span class='hs-definition'>noMixing</span> <span class='hs-keyglyph'>::</span> <a name="line-295"></a> <span class='hs-conid'>Finalizers</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>Finalizers</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Bool</span> <a name="line-296"></a><span class='hs-definition'>noMixing</span> <span class='hs-varid'>ftype0</span> <span class='hs-varid'>r</span> <span class='hs-varid'>mkF</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-297"></a> <span class='hs-layout'>(</span><span class='hs-varid'>ftype</span><span class='hs-layout'>,</span> <span class='hs-varid'>fs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>readIORef</span> <span class='hs-varid'>r</span> <a name="line-298"></a> <span class='hs-keyword'>if</span> <span class='hs-varid'>ftype</span> <span class='hs-varop'>/=</span> <span class='hs-conid'>NoFinalizers</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>ftype</span> <span class='hs-varop'>/=</span> <span class='hs-varid'>ftype0</span> <a name="line-299"></a> <span class='hs-keyword'>then</span> <span class='hs-varid'>error</span> <span class='hs-layout'>(</span><span class='hs-str'>"GHC.ForeignPtr: attempt to mix Haskell and C finalizers "</span> <span class='hs-varop'>++</span> <a name="line-300"></a> <span class='hs-str'>"in the same ForeignPtr"</span><span class='hs-layout'>)</span> <a name="line-301"></a> <span class='hs-keyword'>else</span> <span class='hs-keyword'>do</span> <a name="line-302"></a> <span class='hs-varid'>f</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>mkF</span> <a name="line-303"></a> <span class='hs-varid'>writeIORef</span> <span class='hs-varid'>r</span> <span class='hs-layout'>(</span><span class='hs-varid'>ftype0</span><span class='hs-layout'>,</span> <span class='hs-varid'>f</span> <span class='hs-conop'>:</span> <span class='hs-varid'>fs</span><span class='hs-layout'>)</span> <a name="line-304"></a> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>null</span> <span class='hs-varid'>fs</span><span class='hs-layout'>)</span> <a name="line-305"></a> <a name="line-306"></a><a name="foreignPtrFinalizer"></a><span class='hs-definition'>foreignPtrFinalizer</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>Finalizers</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-307"></a><span class='hs-definition'>foreignPtrFinalizer</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>fs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>readIORef</span> <span class='hs-varid'>r</span><span class='hs-layout'>;</span> <span class='hs-varid'>sequence_</span> <span class='hs-varid'>fs</span> <a name="line-308"></a> <a name="line-309"></a><a name="newForeignPtr_"></a><span class='hs-definition'>newForeignPtr_</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <a name="line-310"></a><span class='hs-comment'>-- ^Turns a plain memory reference into a foreign pointer that may be</span> <a name="line-311"></a><span class='hs-comment'>-- associated with finalizers by using 'addForeignPtrFinalizer'.</span> <a name="line-312"></a><span class='hs-definition'>newForeignPtr_</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span> <span class='hs-varid'>obj</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-313"></a> <span class='hs-varid'>r</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newIORef</span> <span class='hs-layout'>(</span><span class='hs-conid'>NoFinalizers</span><span class='hs-layout'>,</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span> <a name="line-314"></a> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>obj</span> <span class='hs-layout'>(</span><span class='hs-conid'>PlainForeignPtr</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-315"></a> <a name="line-316"></a><a name="touchForeignPtr"></a><span class='hs-definition'>touchForeignPtr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-317"></a><span class='hs-comment'>-- ^This function ensures that the foreign object in</span> <a name="line-318"></a><span class='hs-comment'>-- question is alive at the given place in the sequence of IO</span> <a name="line-319"></a><span class='hs-comment'>-- actions. In particular 'Foreign.ForeignPtr.withForeignPtr'</span> <a name="line-320"></a><span class='hs-comment'>-- does a 'touchForeignPtr' after it</span> <a name="line-321"></a><span class='hs-comment'>-- executes the user action.</span> <a name="line-322"></a><span class='hs-comment'>-- </span> <a name="line-323"></a><span class='hs-comment'>-- Note that this function should not be used to express dependencies</span> <a name="line-324"></a><span class='hs-comment'>-- between finalizers on 'ForeignPtr's. For example, if the finalizer</span> <a name="line-325"></a><span class='hs-comment'>-- for a 'ForeignPtr' @F1@ calls 'touchForeignPtr' on a second</span> <a name="line-326"></a><span class='hs-comment'>-- 'ForeignPtr' @F2@, then the only guarantee is that the finalizer</span> <a name="line-327"></a><span class='hs-comment'>-- for @F2@ is never started before the finalizer for @F1@. They</span> <a name="line-328"></a><span class='hs-comment'>-- might be started together if for example both @F1@ and @F2@ are</span> <a name="line-329"></a><span class='hs-comment'>-- otherwise unreachable, and in that case the scheduler might end up</span> <a name="line-330"></a><span class='hs-comment'>-- running the finalizer for @F2@ first.</span> <a name="line-331"></a><span class='hs-comment'>--</span> <a name="line-332"></a><span class='hs-comment'>-- In general, it is not recommended to use finalizers on separate</span> <a name="line-333"></a><span class='hs-comment'>-- objects with ordering constraints between them. To express the</span> <a name="line-334"></a><span class='hs-comment'>-- ordering robustly requires explicit synchronisation using @MVar@s</span> <a name="line-335"></a><span class='hs-comment'>-- between the finalizers, but even then the runtime sometimes runs</span> <a name="line-336"></a><span class='hs-comment'>-- multiple finalizers sequentially in a single thread (for</span> <a name="line-337"></a><span class='hs-comment'>-- performance reasons), so synchronisation between finalizers could</span> <a name="line-338"></a><span class='hs-comment'>-- result in artificial deadlock. Another alternative is to use</span> <a name="line-339"></a><span class='hs-comment'>-- explicit reference counting.</span> <a name="line-340"></a><span class='hs-comment'>--</span> <a name="line-341"></a><span class='hs-definition'>touchForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>touch</span> <span class='hs-varid'>r</span> <a name="line-342"></a> <a name="line-343"></a><a name="touch"></a><span class='hs-definition'>touch</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ForeignPtrContents</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-344"></a><span class='hs-definition'>touch</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IO</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyword'>case</span> <span class='hs-varid'>touch</span><span class='hs-cpp'>#</span> <span class='hs-varid'>r</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span> <span class='hs-varid'>s'</span> <span class='hs-keyglyph'>-></span> <span class='hs-layout'>(</span><span class='hs-cpp'>#</span> <span class='hs-varid'>s'</span><span class='hs-layout'>,</span> <span class='hs-conid'>()</span> <span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-345"></a> <a name="line-346"></a><a name="unsafeForeignPtrToPtr"></a><span class='hs-definition'>unsafeForeignPtrToPtr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span> <a name="line-347"></a><span class='hs-comment'>-- ^This function extracts the pointer component of a foreign</span> <a name="line-348"></a><span class='hs-comment'>-- pointer. This is a potentially dangerous operations, as if the</span> <a name="line-349"></a><span class='hs-comment'>-- argument to 'unsafeForeignPtrToPtr' is the last usage</span> <a name="line-350"></a><span class='hs-comment'>-- occurrence of the given foreign pointer, then its finalizer(s) will</span> <a name="line-351"></a><span class='hs-comment'>-- be run, which potentially invalidates the plain pointer just</span> <a name="line-352"></a><span class='hs-comment'>-- obtained. Hence, 'touchForeignPtr' must be used</span> <a name="line-353"></a><span class='hs-comment'>-- wherever it has to be guaranteed that the pointer lives on - i.e.,</span> <a name="line-354"></a><span class='hs-comment'>-- has another usage occurrence.</span> <a name="line-355"></a><span class='hs-comment'>--</span> <a name="line-356"></a><span class='hs-comment'>-- To avoid subtle coding errors, hand written marshalling code</span> <a name="line-357"></a><span class='hs-comment'>-- should preferably use 'Foreign.ForeignPtr.withForeignPtr' rather</span> <a name="line-358"></a><span class='hs-comment'>-- than combinations of 'unsafeForeignPtrToPtr' and</span> <a name="line-359"></a><span class='hs-comment'>-- 'touchForeignPtr'. However, the latter routines</span> <a name="line-360"></a><span class='hs-comment'>-- are occasionally preferred in tool generated marshalling code.</span> <a name="line-361"></a><span class='hs-definition'>unsafeForeignPtrToPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>fo</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>fo</span> <a name="line-362"></a> <a name="line-363"></a><a name="castForeignPtr"></a><span class='hs-definition'>castForeignPtr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>b</span> <a name="line-364"></a><span class='hs-comment'>-- ^This function casts a 'ForeignPtr'</span> <a name="line-365"></a><span class='hs-comment'>-- parameterised by one type into another type.</span> <a name="line-366"></a><span class='hs-definition'>castForeignPtr</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unsafeCoerce</span><span class='hs-cpp'>#</span> <span class='hs-varid'>f</span> <a name="line-367"></a> <a name="line-368"></a><a name="finalizeForeignPtr"></a><span class='hs-comment'>-- | Causes the finalizers associated with a foreign pointer to be run</span> <a name="line-369"></a><span class='hs-comment'>-- immediately.</span> <a name="line-370"></a><span class='hs-definition'>finalizeForeignPtr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-371"></a><span class='hs-definition'>finalizeForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>(</span><span class='hs-conid'>PlainPtr</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span> <span class='hs-comment'>-- no effect</span> <a name="line-372"></a><span class='hs-definition'>finalizeForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>foreignPtr</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-373"></a> <span class='hs-layout'>(</span><span class='hs-varid'>ftype</span><span class='hs-layout'>,</span> <span class='hs-varid'>finalizers</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>readIORef</span> <span class='hs-varid'>refFinalizers</span> <a name="line-374"></a> <span class='hs-varid'>sequence_</span> <span class='hs-varid'>finalizers</span> <a name="line-375"></a> <span class='hs-varid'>writeIORef</span> <span class='hs-varid'>refFinalizers</span> <span class='hs-layout'>(</span><span class='hs-varid'>ftype</span><span class='hs-layout'>,</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span> <a name="line-376"></a> <span class='hs-keyword'>where</span> <a name="line-377"></a> <span class='hs-varid'>refFinalizers</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>foreignPtr</span> <span class='hs-keyword'>of</span> <a name="line-378"></a> <span class='hs-layout'>(</span><span class='hs-conid'>PlainForeignPtr</span> <span class='hs-varid'>ref</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>ref</span> <a name="line-379"></a> <span class='hs-layout'>(</span><span class='hs-conid'>MallocPtr</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>ref</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>ref</span> <a name="line-380"></a> <span class='hs-conid'>PlainPtr</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-></span> <a name="line-381"></a> <span class='hs-varid'>error</span> <span class='hs-str'>"finalizeForeignPtr PlainPtr"</span> <a name="line-382"></a> </pre></body> </html>