This module provides two kinds of stable references to Haskell objects, stable names and stable pointers.
A 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
deRefStablePtr
on the stable pointer object it has.
The Haskell interface provided by the Stable
module is as follows:
data StablePtr a -- abstract, instance of: Eq.
makeStablePtr :: a -> IO (StablePtr a)
deRefStablePtr :: StablePtr a -> IO a
freeStablePtr :: StablePtr a -> IO ()
Care must be taken to free stable pointers that are no longer required
using the freeStablePtr
function, otherwise two bad things can
happen:
Notes:
sp1 :: StablePtr
and sp2 :: StablePtr
and sp1
== sp2
then sp1
and sp2
are either the same stable pointer,
or they were created by calls to makeStablePtr
on the same
object. Another way to say this is "every time you call
makeStablePtr
on an object you get back the same stable pointer".deRefStablePtr
on a stable pointer which has previously been
freed results in undefined behaviour.The C interface (which is brought into scope by #include
<Stable.h>
) is as follows:
typedef StablePtr /* abstract, probably an unsigned long */
extern StgPtr deRefStablePtr(StgStablePtr stable_ptr);
static void freeStablePtr(StgStablePtr sp);
static StgStablePtr splitStablePtr(StgStablePtr sp);
The functions deRefStablePtr
and freeStablePtr
are
equivalent to the Haskell functions of the same name above.
The function splitStablePtr
allows a stable pointer to be
duplicated without making a new one with makeStablePtr
. The
stable pointer won't be removed from the runtime system's internal
table until freeStablePtr
is called on both pointers.
A haskell object can be given a stable name by calling
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:
data StableName a -- abstract, instance Eq.
makeStableName :: a -> IO (StableName a)
hashStableName :: StableName a -> Int
All these operations run in constant time.
Stable names have the following properties:
sn1 :: StablePtr
and sn2 :: StablePtr
and sn1
== sn2
then sn1
and sn2
are either the same stable name,
or they were created by calls to makeStableName
on the same
object.freeStableName
operation. Stable names are
reclaimed by the runtime system when they are no longer needed.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. hashStableName
operation, which converts a
stable name to an Int
. The 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.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 Int
for hashing.