Alastair:
>> Merging Ptr and ForeignPtr still seems like a cool idea.  One less
>> type, eliminate some conversion functions between near-iromorphic
>> types, easier to switch between automatic and manual reclamation.

SimonM:
> er... but I explained why we didn't do this in GHC.  Admittedly it's
> only for performance reasons - we want the compiler to be able to
> unbox Ptr when it can.  

I thought (maybe I misread) that you explained it as being a
historical artifact caused by 'Ptr a' being implemented by 'Addr#'
instead of 'Ptr# a'.

But what you seem to be hinting at is that it's really caused by
unboxing: if it is unboxed, it isn't allocated in the heap, it isn't
visible to the GC, and evaluation may cause loss of sharing (which
makes it harder to know when the finalizers should run).

SimonM:
> But it's quite a big win.

I guess those Ptr's which have finalizers attached (in a world where
Ptr and ForeignPtr are merged) would not have pointer arithmetic done
on them so I'd guess the win is small there (which is why it's ok that
ForeignPtrs are boxed).

But those Ptr's which don't have finalizers attached often have
arithmetic done on them which makes it costly to keep them boxed all
the time.


Which makes me think that the current distinction between Ptr and
ForeignPtr is a good idea not because of the performance but because
of questions like:

- If I attach a finalizer to 'p', does 'p `plusPtr` 1' have a finalizer
  attached too?

- What about 'p `plusPtr` 1 `plusPtr` (-1)' or 'p `plusPtr` 0'


Or, to put it another way, the reason we have the distinction is to
enforce the rule that ForeignPtrs are only created in the IO monad.
This is necessary so that we can clearly answer questions about
sharing for ForeignPtrs and so that addition of finalizers to
ForeignPtrs is reliably sequenced by the IO monad instead of being
subject to the vagaries of choice of evaluation order.  

Note that the other things you said you find it useful to attach
finalizers to (MVars and WeakPtrs) are in the same boat: they are
objects created in the IO monad.  In fact, they are almost the only
other thing created in the IO monad so it's not surprising that
they're the only objects you find it useful to attach finalizers to.

Off the top of my head, the only other objects created in the IO monad
are Threads.  It's almost irrelevant to provide finalizers for them
because they _tend_ to 'know' when they are exiting.  But, there's one
case where they can be terminated without explicitly exiting: if a
thread is blocked on an MVar which becomes garbage, the thread is
silently garbage collected (at least, that used to be the story).  In
this case, I think it'd be really useful to be able to run a finalizer.


So it seems like the distinction is not for performance reasons or due
to historical accident but semantic reasons.  Oh well, another
possible simplification bits the dust.  Now back to our regularily
scheduled discussion of problems implementing Haskell finalizers.

--
Alastair
_______________________________________________
Cvs-ghc mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to