[Haskell] Re: ANN: HDBC (Haskell Database Connectivity)
A.Simon at kent.ac.uk
Mon Jan 9 06:18:20 EST 2006
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.
More information about the Haskell