Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Addr# type, and how can I use it?

I've recently been looking around at various Haskell quirks, like unboxed types and whatnot, when I discovered the Addr# type.

The GHC.Prim package describes it as so:

An arbitrary machine address assumed to point outside the garbage-collected heap.

And that means not much to me.

Furthermore, I keep finding functions like this that use the type:

readIntOffAddr# :: Addr# -> Int# -> State# s -> (#State# s, Int##)

What is this type? What can I do with it? Why is it necessary?

like image 936
AJF Avatar asked Dec 01 '22 14:12

AJF


2 Answers

As a complement to Michael's answer:

Addr# is the unboxed type underlying a Ptr a in the same way that Int# is the unboxed type underlying an Int. Its contents are presumably to be interpreted as a machine address, though as far as the compiler and GC are concerned it is just another integral type (of whatever size pointers are on the system in question). Since it is an arbitrary machine address and not a GC-managed pointer, it should presumably not point into the Haskell heap because the addresses of Haskell heap objects are not stable as viewed from the level of Haskell (a GC could occur at any point in your program, and then whatever object your Addr# pointed at now lives elsewhere, or nowhere at all).

Normally a Ptr a/Addr# will contain a pointer returned from malloc/mmap/etc., or a pointer to a C global variable, or in general any sort of thing that a pointer might sensibly point to in a C program. You would normally use readIntOffAddr# when interfacing with a C function that returns or modifies the contents of a passed HsInt *. (Well, you wouldn't use it directly, you'd use Int's peekElemOff Storable method which I presume is implemented in terms of readIntOffAddr#, or you would use an even higher-level function like peekArray).

like image 120
Reid Barton Avatar answered Dec 19 '22 19:12

Reid Barton


The equivalent* C code would be:

long readIntOffAddr(long *ptr, long offset) {
    return ptr[offset];
}

Addr# is just like void *. The function has an IO-like signature because it is not "pure". Multiple calls to the function may return different values (obviously).

* Update (2018): I just learned that equating C's int type with Haskells Int# type is wrong. So I changed int to long in the above code snippet. This is also (maybe) not 100% correct, but at least it is true for all GHC implementations that I have seen. In GHC versions 6-8 (haven't checked others), Int# is 32 bit wide on 32-bit platforms and 64 bit wide on 64-bit platforms. This matches the behaviour of GCC for long for all C/C++ implementations on 32-bit and 64-bit platforms that I am aware of, so I think equating Int# with long is a good first approximation. No one noticed this minor inaccuracy in the last 3 years (or cared enough to edit/comment). I doubt that there is any Haskell/Platform/C combination where HsInt != long where the Haskell implementation has a readIntOffAddr# function.. please prove me wrong.

like image 20
Michael Avatar answered Dec 19 '22 18:12

Michael