Skip to content
Snippets Groups Projects
Commit 111d9435 authored by Simon Marlow's avatar Simon Marlow
Browse files

[project @ 1999-01-26 12:24:57 by simonm]

More stable name additions/changes.
parent ed4cd6d4
No related merge requests found
<sect> <idx/Stable/
<label id="sec:Stable">
<p>
This module provides two kinds of stable references to Haskell
objects, stable names and stable pointers.
<sect1> <idx/Stable Pointers/
<label id="sec:stable-pointers">
<p>
A <em/stable pointer/ is a reference to a Haskell expression that
can be passed to foreign functions via the foreign function
interface.
Normally a Haskell object will move around from time to time, because
of garbage collection, hence we can't just pass the address of an
object to a foreign function and expect it to remain valid. Stable
pointers provide a level of indirection so that the foreign code can
get the "real address" of the Haskell object by calling
<tt/deRefStablePtr/ on the stable pointer object it has.
The Haskell interface provided by the <tt/Stable/ module is as follows:
<tscreen><verb>
data StablePtr a -- abstract, instance of: Eq.
makeStablePtr :: a -> IO (StablePtr a)
deRefStablePtr :: StablePtr a -> IO a
freeStablePtr :: StablePtr a -> IO ()
</verb></tscreen>
Care must be taken to free stable pointers that are no longer required
using the <tt/freeStablePtr/ function, otherwise two bad things can
happen:
<itemize>
<item> The object referenced by the stable pointer will be retained in
the heap.
<item> The runtime system's internal stable pointer table will grow,
which imposes an overhead on garbage collection.
</itemize>
Notes:
<itemize>
<item> If <tt/sp1 :: StablePtr/ and <tt/sp2 :: StablePtr/ and <tt/sp1
== sp2/ then <tt/sp1/ and <tt/sp2/ are either the same stable pointer,
or they were created by calls to <tt/makeStablePtr/ on the same
object. Another way to say this is "every time you call
<tt/makeStablePtr/ on an object you get back the same stable pointer".
<item> The reverse is not necessarily true: if two stable pointers are
not equal, it doesn't mean that they don't refer to the same Haskell
object (although they probably don't). <item> Calling
<tt/deRefStablePtr/ on a stable pointer which has previously been
freed results in undefined behaviour.
</itemize>
The C interface (which is brought into scope by <tt/#include
&lt;Stable.h&gt;/) is as follows:
<tscreen><verb>
typedef StablePtr /* abstract, probably an unsigned long */
extern StgPtr deRefStablePtr(StgStablePtr stable_ptr);
static void freeStablePtr(StgStablePtr sp);
static StgStablePtr splitStablePtr(StgStablePtr sp);
</verb></tscreen>
The functions <tt/deRefStablePtr/ and <tt/freeStablePtr/ are
equivalent to the Haskell functions of the same name above.
The function <tt/splitStablePtr/ allows a stable pointer to be
duplicated without making a new one with <tt/makeStablePtr/. The
stable pointer won't be removed from the runtime system's internal
table until <tt/freeStablePtr/ is called on both pointers.
<sect1>Stable Names
<label id="sec:stable-pointers">
<p>
A haskell object can be given a <em/stable name/ by calling
<tt/makeStableName/ on it. Stable names solve the following problem:
suppose you want to build a hash table with Haskell objects as keys,
but you want to use pointer equality for comparison; maybe because the
keys are large and hashing would be slow, or perhaps because the keys
are infinite in size. We can't build a hash table using the address
of the object as the key, because objects get moved around by the
garbage collector, meaning a re-hash would be necessary after every
garbage collection.
Enter stable names. A stable name is an abstract entity that supports
equality and hashing, with the following interface:
<tscreen><verb>
data StableName a -- abstract, instance Eq.
makeStableName :: a -> IO (StableName a)
hashStableName :: StableName a -> Int
</verb></tscreen>
All these operations run in constant time.
Stable names have the following properties:
<enum>
<item> If <tt/sn1 :: StablePtr/ and <tt/sn2 :: StablePtr/ and <tt/sn1
== sn2/ then <tt/sn1/ and <tt/sn2/ are either the same stable name,
or they were created by calls to <tt/makeStableName/ on the same
object.
<item> The reverse is not necessarily true: if two stable names are
not equal, it doesn't mean that they don't refer to the same Haskell
object (although they probably don't).
<item> There is no <tt/freeStableName/ operation. Stable names are
reclaimed by the runtime system when they are no longer needed.
<item> There is no <tt/deRefStableName/ operation. You can't get back
from a stable name to the original Haskell object. The reason for
this is that the existence of a stable name for an object doesn't
guarantee the existence of the object itself; it can still be garbage
collected.
<item> There is a <tt/hashStableName/ operation, which converts a
stable name to an <tt/Int/. The <tt/Int/ returned is not necessarily
unique (that is, it doesn't satisfy property (1) above), but it can be
used for building hash tables of stable names.
</enum>
Properties (1) and (2) are similar to stable pointers, but the key
differences are that you can't get back to the original object from a
stable name, and you can convert one to an <tt/Int/ for hashing.
%
% (c) The AQUA Project, Glasgow University, 1994-1996
% (c) The AQUA Project, Glasgow University, 1994-1998
%
\section[Foreign]{Module @Foreign@}
......@@ -22,6 +22,7 @@ module Foreign
) where
import PrelForeign --hiding ( makeForeignObj )
import PrelStable
--import qualified PrelForeign as PF ( makeForeignObj )
import PrelBase ( Int(..), Double(..), Float(..), Char(..) )
import PrelGHC ( indexCharOffForeignObj#, indexIntOffForeignObj#,
......
......@@ -89,6 +89,7 @@ import PrelArr
import PrelAddr
import PrelArrExtra
import PrelForeign
import PrelStable
import PrelST
import ST
import Ix
......
% -----------------------------------------------------------------------------
% $Id: Stable.lhs,v 1.1 1999/01/26 12:24:58 simonm Exp $
%
% (c) The GHC Team, 1999
%
\section[Stable]{Module @Stable@}
\begin{code}
module Stable
( StableName {-a-} -- abstract.
, makeStableName -- :: a -> IO (StableName a)
, hashStableName -- :: StableName a -> Int
, StablePtr {-a-} -- abstract.
, makeStablePtr -- :: a -> IO (StablePtr a)
, deRefStablePtr -- :: StablePtr a -> IO a
, freeStablePtr -- :: StablePtr a -> IO ()
)
where
import PrelBase
import PrelIOBase
import PrelStable
-----------------------------------------------------------------------------
-- Stable Names
data StableName a = StableName (StableName# a)
makeStableName :: a -> IO (StableName a)
hashStableName :: StableName a -> Int
makeStableName a = IO $ \ s ->
case makeStableName# a s of (# s', sn #) -> (# s', StableName sn #)
hashStableName (StableName sn) = I# (stableNameToInt# sn)
instance Eq (StableName a) where
(StableName sn1) == (StableName sn2) =
case eqStableName# sn1 sn2 of
0# -> False
_ -> True
\end{code}
......@@ -58,7 +58,7 @@ PrelNumExtra_HC_OPTS += -H30m -K2m
PrelBase_HC_OPTS += -H10m
PrelRead_HC_OPTS += -H16m
PrelTup_HC_OPTS += -H12m
PrelNum_HC_OPTS += -H12m -K3m
PrelNum_HC_OPTS += -H12m -K4m
PrelArr_HC_OPTS += -H8m
PrelHandle_HC_OPTS += -H14m
Time_HC_OPTS += -H18m
......
......@@ -41,7 +41,7 @@ import PrelPack ( packString )
import PrelArr ( ByteArray(..) )
#ifndef __PARALLEL_HASKELL__
import PrelForeign ( StablePtr, deRefStablePtr )
import PrelStable ( StablePtr, deRefStablePtr )
#endif
---------------------------------------------------------------
......
......@@ -57,52 +57,6 @@ instance Eq ForeignObj where
#endif /* !__PARALLEL_HASKELL__ */
\end{code}
%*********************************************************
%* *
\subsection{Type @StablePtr@ and its operations}
%* *
%*********************************************************
\begin{code}
#ifndef __PARALLEL_HASKELL__
data StablePtr a = StablePtr (StablePtr# a)
instance CCallable (StablePtr a)
instance CCallable (StablePtr# a)
instance CReturnable (StablePtr a)
-- Nota Bene: it is important {\em not\/} to inline calls to
-- @makeStablePtr#@ since the corresponding macro is very long and we'll
-- get terrible code-bloat.
makeStablePtr :: a -> IO (StablePtr a)
deRefStablePtr :: StablePtr a -> IO a
freeStablePtr :: StablePtr a -> IO ()
{-# INLINE deRefStablePtr #-}
{-# INLINE freeStablePtr #-}
makeStablePtr f = IO $ \ rw1# ->
case makeStablePtr# f rw1# of
(# rw2#, sp# #) -> (# rw2#, StablePtr sp# #)
deRefStablePtr (StablePtr sp#) = IO $ \ rw1# ->
deRefStablePtr# sp# rw1#
freeStablePtr sp = _ccall_ freeStablePointer sp
eqStablePtr :: StablePtr a -> StablePtr b -> Bool
eqStablePtr (StablePtr sp1#) (StablePtr sp2#) =
case eqStablePtr# sp1# sp2# of
0# -> False
_ -> True
instance Eq (StablePtr a) where
p == q = eqStablePtr p q
p /= q = not (eqStablePtr p q)
#endif /* !__PARALLEL_HASKELL__ */
\end{code}
%*********************************************************
%* *
\subsection{Unpacking Foreigns}
......
......@@ -298,6 +298,12 @@ indexWord64OffForeignObj#
makeStablePtr#
deRefStablePtr#
eqStablePtr#
StableName#
makeStableName#
eqStableName#
stableNameToInt#
reallyUnsafePtrEquality#
unsafeCoerce#
......
% -----------------------------------------------------------------------------
% $Id: PrelStable.lhs,v 1.1 1999/01/26 12:25:01 simonm Exp $
%
% (c) The GHC Team, 1992-1999
%
\begin{code}
{-# OPTIONS -fno-implicit-prelude #-}
module PrelStable
( StablePtr(..)
, makeStablePtr -- :: a -> IO (StablePtr a)
, deRefStablePtr -- :: StablePtr a -> a
, freeStablePtr -- :: StablePtr a -> IO ()
) where
import PrelBase
import PrelIOBase
-----------------------------------------------------------------------------
-- Stable Pointers
data StablePtr a = StablePtr (StablePtr# a)
instance CCallable (StablePtr a)
instance CCallable (StablePtr# a)
instance CReturnable (StablePtr a)
makeStablePtr :: a -> IO (StablePtr a)
deRefStablePtr :: StablePtr a -> IO a
freeStablePtr :: StablePtr a -> IO ()
makeStablePtr a = IO $ \ s ->
case makeStablePtr# a s of (# s', sp #) -> (# s', StablePtr sp #)
deRefStablePtr (StablePtr sp) = IO $ \s -> deRefStablePtr# sp s
freeStablePtr sp = _ccall_ freeStablePtr sp
instance Eq (StablePtr a) where
(StablePtr sp1) == (StablePtr sp2) =
case eqStablePtr# sp1 sp2 of
0# -> False
_ -> True
\end{code}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment