Help me grok addFinalizer
Simon Marlow
marlowsd at gmail.com
Fri Feb 17 13:30:52 CET 2012
On 16/02/2012 22:20, Michael Craig wrote:
> > I haven't checked, but ...
>
> I checked, and your solution works. In the context of a larger program,
> getting NOLINE pragmas in all the right places would be challenging,
> wouldn't it?
>
> I found a bug report on the GHC Trac [1] in which Simon explains the
> importance of evaluating the thunk before calling addFinalizer.
> (Otherwise the finalizer is added to the thunk.) This works:
>
> newThing :: IO Thing
> newThing = do
> x <- Thing `fmap` newIORef True
> return $ unsafePerformIO ( do
> x' <- evaluate x
> addFinalizer x' $ putStrLn "running finalizer" ) `seq` x
>
> If anyone can show me how to get rid of unsafePerformIO in there, that'd
> be great. Tried a few things to no avail.
If your goal is to add a finalizer to an IORef, I would use
Data.IORef.mkWeakIORef. It adds the finalizer to the actual primitive
MutVar# object inside the IORef, so it's a lot more predictable (the
primitive object can't be copied under your feet).
> > Finalizers are tricky things, especially when combined with some of
>> GHC's optimisations.
>
> No kidding!
Finalizers on ordinary Haskell objects are very limited in usefulness,
the only good use I've found is for memo tables.
Cheers,
Simon
>
> [1] http://hackage.haskell.org/trac/ghc/ticket/5365
>
> Mike Craig
>
>
>
> On Thu, Feb 16, 2012 at 4:15 PM, Ian Lynagh <igloo at earth.li
> <mailto:igloo at earth.li>> wrote:
>
> On Thu, Feb 16, 2012 at 02:55:13PM -0600, Austin Seipp wrote:
> > 64-bit GHC on OS X gives me this:
> >
> > $ ghc -fforce-recomp -threaded finalizer
> > [1 of 1] Compiling Main ( finalizer.hs, finalizer.o )
> > Linking finalizer ...
> > $ ./finalizer
> > waiting ...
> > done!
> > waiting ...
> > running finalizer
> > done!
> >
> > However, it's a different story when `-O2` is specified:
> >
> > $ ghc -O2 -fforce-recomp -threaded finalizer
> > [1 of 1] Compiling Main ( finalizer.hs, finalizer.o )
> > Linking finalizer ...
> > $ ./finalizer
> > waiting ...
> > running finalizer
> > done!
> > waiting ...
> > done!
> >
> > This smells like a bug. The stranger thing is that the GC will
> run the
> > finalizer, but it doesn't reclaim the object? I'd think `readIORef`
> > going after an invalidated pointer the GC reclaimed would almost
> > certainly crash.
>
> The finalizer is attached to the Thing, not the IORef. I haven't
> checked, but I assume that ioref gets inlined, so effectively (ioref x)
> is evaluated early. If you change it to
>
> readIORef (ioref' x) >>= \ix -> ix `seq` return ()
>
> and define
>
> {-# NOINLINE ioref' #-}
> ioref' :: Thing -> IORef Bool
> ioref' = ioref
>
> then you'll get the sort of output you expect.
>
> Finalizers are tricky things, especially when combined with some of
> GHC's optimisations.
>
>
> Thanks
> Ian
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> <mailto:Glasgow-haskell-users at haskell.org>
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>
>
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
More information about the Glasgow-haskell-users
mailing list