Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > f9b127c02f56e71454a7233185e51eb4 > files > 839

ghc-base-devel-4.3.1.0-16.fc15.i686.rpm

<?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'>-&gt;</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'>-&gt;</span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</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'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</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'>&lt;-</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'>=&gt;</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'>-- &gt;    do { p &lt;- 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'>=&gt;</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>-&gt;</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'>&lt;</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 &gt;= 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'>&lt;-</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>&lt;</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 &gt;= 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'>&lt;-</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'>-&gt;</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'>-&gt;</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'>=&gt;</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'>=&gt;</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>-&gt;</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'>&lt;</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 &gt;= 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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>&lt;</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 &gt;= 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'>-&gt;</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'>-&gt;</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'>-&gt;</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</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'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&gt;&gt;</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'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&gt;&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>env</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ForeignPtr</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</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'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&gt;&gt;</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'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>r</span> <span class='hs-varop'>&gt;&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</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'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</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'>&lt;-</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>&lt;-</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>&lt;-</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'>&amp;&amp;</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'>&lt;-</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'>-&gt;</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'>&lt;-</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'>-&gt;</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'>&lt;-</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>-&gt;</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'>&lt;-</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'>-&gt;</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'>-&gt;</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'>-&gt;</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>