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
