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.
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? Ben