[project @ 1999-01-26 12:24:57 by simonm]
authorsimonm <unknown>
Tue, 26 Jan 1999 12:25:02 +0000 (12:25 +0000)
committersimonm <unknown>
Tue, 26 Jan 1999 12:25:02 +0000 (12:25 +0000)
More stable name additions/changes.

ghc/docs/libraries/Stable.sgml [new file with mode: 0644]
ghc/lib/exts/Foreign.lhs
ghc/lib/exts/MutableArray.lhs
ghc/lib/exts/Stable.lhs [new file with mode: 0644]
ghc/lib/std/Makefile
ghc/lib/std/PrelErr.lhs
ghc/lib/std/PrelForeign.lhs
ghc/lib/std/PrelGHC.hi-boot
ghc/lib/std/PrelStable.lhs [new file with mode: 0644]

diff --git a/ghc/docs/libraries/Stable.sgml b/ghc/docs/libraries/Stable.sgml
new file mode 100644 (file)
index 0000000..2d1dc36
--- /dev/null
@@ -0,0 +1,126 @@
+<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.
index 2187d53..cff2424 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (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#, 
index 202c297..55174c7 100644 (file)
@@ -89,6 +89,7 @@ import PrelArr
 import PrelAddr
 import PrelArrExtra
 import PrelForeign
+import PrelStable
 import PrelST
 import ST
 import Ix
diff --git a/ghc/lib/exts/Stable.lhs b/ghc/lib/exts/Stable.lhs
new file mode 100644 (file)
index 0000000..534b851
--- /dev/null
@@ -0,0 +1,47 @@
+% -----------------------------------------------------------------------------
+% $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}
index 81feb53..d32470f 100644 (file)
@@ -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
index a96044c..70b3f47 100644 (file)
@@ -41,7 +41,7 @@ import PrelPack     ( packString )
 import PrelArr      ( ByteArray(..) )
 
 #ifndef __PARALLEL_HASKELL__
-import PrelForeign  ( StablePtr, deRefStablePtr )
+import PrelStable  ( StablePtr, deRefStablePtr )
 #endif
 
 ---------------------------------------------------------------
index a61d27a..f149108 100644 (file)
@@ -59,52 +59,6 @@ instance Eq ForeignObj where
 
 %*********************************************************
 %*                                                     *
-\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}
 %*                                                     *
 %*********************************************************
index 1a1cbe8..f9e879c 100644 (file)
@@ -298,6 +298,12 @@ indexWord64OffForeignObj#
   makeStablePtr#
   deRefStablePtr#
   eqStablePtr#
+
+  StableName#
+  makeStableName#
+  eqStableName#
+  stableNameToInt#
+
   reallyUnsafePtrEquality#
 
   unsafeCoerce#
diff --git a/ghc/lib/std/PrelStable.lhs b/ghc/lib/std/PrelStable.lhs
new file mode 100644 (file)
index 0000000..664ade7
--- /dev/null
@@ -0,0 +1,45 @@
+% -----------------------------------------------------------------------------
+% $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}