Thoughts on unsafeLocalState

Dan Knapp dankna at gmail.com
Sun Feb 20 00:10:03 CET 2011


Hi,

First off, this is my first time posting to this list.  I hope my post is
appropriate!

I noticed in going through the API docs that we now have unsafeLocalState in
Foreign.Marshal, which currently is defined as equivalent to
unsafePerformIO, but with a note that it "is likely to be replaced".  I did
look through the archives of this list, but found no discussion of it.  The
description of it in the API docs is simply:

Sometimes an external entity is a pure function, except that it passes
arguments and/or results via pointers. The function unsafeLocalState permits
the packaging of such entities as pure functions.
The only IO operations allowed in the IO action passed to unsafeLocalState
are (a) local allocation (alloca, allocaBytes and derived operations such as
withArray and withCString), and (b) pointer operations (Foreign.Storable and
Foreign.Ptr) on the pointers to local storage, and (c) foreign functions
whose only observable effect is to read and/or write the locally allocated
memory. Passing an IO operation that does not obey these rules results in
undefined behaviour.
It is expected that this operation will be replaced in a future revision of
Haskell


I found a more complete explanation at the bottom of:

http://hackage.haskell.org/trac/haskell-prime/wiki/ForeignFunctionInterface

(Scroll to "Considerations for the future".)

The notion seems to be that we would create a new monad that only allows
specific actions to be taken.

This is great as far as it goes.  I very much support the idea, and would
switch my code to use it if it were developed.  However, I think the
restrictions as given in the text I quoted above are too tight.  Ideally we
want something that would be suitable for libraries such as ByteString,
which I believe wraps the allocation of data on the foreign heap in pure
functions.  This would not be allowed by unsafeLocalState in the form given,
because the only pointer operations allowed by clause (b) are those on
memory that is allocated in temporary fashion as by clause (a).  I'm not
sure quite how to word this, but I think perhaps broadening clause (a) to
also allow allocation of ForeignPtrs, effectively changing the restriction
from "anything you allocate must be freed by the time you return" to
"anything you allocate must be known to the garbage collector".

I have a practical use for this; I am working on a binding to libffi,
pursuant to developing a better ObjC/Cocoa binding.  To use libffi, it is
necessary to build complicated structs.  So I have the definition type
ComplicatedStruct = ForeignPtr (), and a function, currently wrapped in
unsafePerformIO, which constructs a new complicated struct given a
description of what it should contain.  This is, in my understanding, a
"safe" usage of unsafePerformIO, but really it would be nice to use
something safer.

So I don't know that I have an action item, I just wanted to make sure that
if and when future development on this happens, it takes this concern into
account.  Um, thanks for reading?

-- 
Dan Knapp
"An infallible method of conciliating a tiger is to allow oneself to be
devoured." (Konrad Adenauer)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-prime/attachments/20110219/86d7f51b/attachment.htm>


More information about the Haskell-prime mailing list