On Mon, 2006-01-09 at 11:33 +0100, Benjamin Franksen wrote: > On Monday 09 January 2006 10:03, Axel Simon wrote: > > On Sun, 2006-01-08 at 14:51 +0000, Keean Schupke wrote: > > > My solution to this when developing a database library for my own > > > use was to define the API > > > in a bracket notation style, and only provide safe functions. The > > > idea is that the function obtains the resource, calls a function > > > passed as an argument, then frees the resource, so all resouces are > > > guaranteed to be freed in the correct order... for example: > > > > > > dbConnectWith :: DbName -> (DbHandle -> IO Result) -> Result > > > dbConnectWith name workFn = do > > > handle <- dbConnectTo name > > > workFn handle `finally` dbDisconnect handle > > > > > > In this way you avoid finalizers... and everthing is safe providing > > > you only export the "with" style functions from the library... > > > Here's an example from the library, the connect function: > > > > I suppose you meant to write "result" rather than "Result". This > > style of functions is only safe if the user ensures that DbHandle is > > never returned as part of the result. You should have that in your > > documentation. > > I wanted to mention this too, but you were quicker ;) > > > As far as I can tell, the only general solution is to use finalizers > > and, if you really need to enforce a sequence of finialization, > > touchForeignPtr. > > Repeat: touchForeignPtr can NOT be used to enforce finalization order.
Ok, I re-read that thread. I agree. However, it is likely that the library you're using allows connections to be freed after the database is freed. If not, you can still all three methods I posted to get around the problem: Each connection needs to ref the database pointer and deref that pointer when the finalizer is run. That way, the database is never dead until all finalizers of all connections are run. > > A practical issue with touchForeignPtr is that it > > cannot be conveniently called from another finalizer, since the > > latter live in C. > > What do you mean "live in C"? Can't or shouldn't finalizers be written > in Haskell, too? Well, before ghc 6.0 and the "new FFI", finalizers where Haskell functions. Since this was tricky to implement, so finalizers are now C functions. This has other implications, e.g. you can't pass a closure of several pointers to the C function, the C finalizer will just get the one pointer it wraps. Axel. _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell