caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* exception safety / RAII ?
@ 2005-03-05 18:16 Michael Benfield
  2005-03-05 18:44 ` [Caml-list] " Gerd Stolpmann
  2005-03-07  0:03 ` Jon Harrop
  0 siblings, 2 replies; 36+ messages in thread
From: Michael Benfield @ 2005-03-05 18:16 UTC (permalink / raw)
  To: caml-list

I'm looking at OCaml coming from sort of a C++ background and I'm 
finding it really exciting.

There's one thing that worries me though. C++ programmers have been 
dealing with issues of exception safety for years - it's a complicated 
problem because coding in the presence of exceptions for all intents 
and purposes means your function could end at any point, so how can you 
make sure resources are deallocated? The C++ solution to this problem 
is a technique called Resource Acquisition Is Initialization. C++ 
objects have destructors, which are simply functions that will always 
be called on exit from a scope - including if the exit is caused by an 
exception coming up through your function. You make resource release 
(whether the resource is memory, a socket, whatever) happen in a 
destructor, and then you are set. This is very handy even disregarding 
exceptions.

So I'm just wondering what facilities OCaml has to either implement 
this concept, or other concepts to help with exception safety? The 
OCaml manual says: "Also, finalization can be performed by trapping all 
exceptions, performing the finalization, then raising again the 
exception". This makes me cringe.


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] exception safety / RAII ?
  2005-03-05 18:16 exception safety / RAII ? Michael Benfield
@ 2005-03-05 18:44 ` Gerd Stolpmann
  2005-03-07  0:03 ` Jon Harrop
  1 sibling, 0 replies; 36+ messages in thread
From: Gerd Stolpmann @ 2005-03-05 18:44 UTC (permalink / raw)
  To: Michael Benfield; +Cc: caml-list

Am Samstag, den 05.03.2005, 13:16 -0500 schrieb Michael Benfield:
> I'm looking at OCaml coming from sort of a C++ background and I'm 
> finding it really exciting.
> 
> There's one thing that worries me though. C++ programmers have been 
> dealing with issues of exception safety for years - it's a complicated 
> problem because coding in the presence of exceptions for all intents 
> and purposes means your function could end at any point, so how can you 
> make sure resources are deallocated? 

This is not as complicated as for C++. Memory is deallocated
automatically by the garbage collector. The remaining resources are
usually handled manually, e.g. for files

let f = open_in ... in
try
  ...  (* code may raise arbitrary exception *)
with
  any_exception ->
    close_in f;
    raise any_exception

If that happens frequently, one can also define higher-order functions
for that purpose, e.g.

let with_in_file f fn =
  try 
    let r = fn f in close_in f; r
  with
    any_exception -> 
      close_in f; 
      raise any_exception

and then

with_in_file 
  (open_in ...)
  (fun f -> ...)

> The C++ solution to this problem 
> is a technique called Resource Acquisition Is Initialization. C++ 
> objects have destructors, which are simply functions that will always 
> be called on exit from a scope - including if the exit is caused by an 
> exception coming up through your function. You make resource release 
> (whether the resource is memory, a socket, whatever) happen in a 
> destructor, and then you are set. This is very handy even disregarding 
> exceptions.
> 
> So I'm just wondering what facilities OCaml has to either implement 
> this concept, or other concepts to help with exception safety? The 
> OCaml manual says: "Also, finalization can be performed by trapping all 
> exceptions, performing the finalization, then raising again the 
> exception". This makes me cringe.

Using finalization functions is often a bad idea. You cannot predict
when they are called. For example, if one tried to close files by
finalization it would be very likely to run out of file descriptors
because finalization is deferred to some unknown point in time in the
future.

The main purpose of finalization is to synchronize O'Caml's memory
management with some foreign mechanism, e.g. because one is calling a
foreign library.

So the simplified answer to your question: There is nothing like RAII,
and one does not miss it, because O'Caml has much better concepts.

Gerd
-- 
------------------------------------------------------------
Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
------------------------------------------------------------



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] exception safety / RAII ?
  2005-03-05 18:16 exception safety / RAII ? Michael Benfield
  2005-03-05 18:44 ` [Caml-list] " Gerd Stolpmann
@ 2005-03-07  0:03 ` Jon Harrop
  2005-03-07  1:32   ` Stefan Monnier
  2005-03-07  3:31   ` [Caml-list] " Michael Walter
  1 sibling, 2 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-07  0:03 UTC (permalink / raw)
  To: caml-list

On Saturday 05 March 2005 18:16, Michael Benfield wrote:
> I'm looking at OCaml coming from sort of a C++ background and I'm
> finding it really exciting.

Yes, it is an excellent language, far better than C++ for virtually all tasks. 
I do suggest that you try to shed most of the C++ ways of thinking though, as 
the vast majority of them do not apply to OCaml. In particular, forget about 
iterators and OOP.

> There's one thing that worries me though. C++ programmers have been
> dealing with issues of exception safety for years - it's a complicated
> problem because coding in the presence of exceptions for all intents
> and purposes means your function could end at any point, so how can you
> make sure resources are deallocated?

This is only a complicated problem if you do not have a garbage collector, 
which OCaml does.

> The C++ solution to this problem 
> is a technique called Resource Acquisition Is Initialization.

This is a poor man's alternative to garbage collection. The principal problem 
is the inability to determine what object owns which resources at any given 
point in the code.

> C++ 
> objects have destructors, which are simply functions that will always
> be called on exit from a scope - including if the exit is caused by an
> exception coming up through your function. You make resource release
> (whether the resource is memory, a socket, whatever) happen in a
> destructor, and then you are set. This is very handy even disregarding
> exceptions.

In OCaml, any internal resources are transparently deallocated by the garbage 
collector so you do not need to worry. In the relatively unlikely event of an 
external resource, you can either explicitly deallocate yourself or you can 
wrap the resource in an OCaml object and set the finaliser of the object to 
deallocate the resource for you. In theory, this could take forever to 
deallocate. In practice, resources are deallocated extremely quickly.

> So I'm just wondering what facilities OCaml has to either implement
> this concept, or other concepts to help with exception safety? The
> OCaml manual says: "Also, finalization can be performed by trapping all
> exceptions, performing the finalization, then raising again the
> exception". This makes me cringe.

This can be done much more elegantly in OCaml than in C++. Do you know how 
this is done in OCaml?

In most cases you probably won't care when a file is closed after writing to 
it, so you can just rely on the garbage collector. In the few cases that you 
do mind, this is neither difficult nor complicated to implement.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: exception safety / RAII ?
  2005-03-07  0:03 ` Jon Harrop
@ 2005-03-07  1:32   ` Stefan Monnier
  2005-03-07  2:48     ` [Caml-list] " Brian Hurt
  2005-03-07 13:30     ` Jon Harrop
  2005-03-07  3:31   ` [Caml-list] " Michael Walter
  1 sibling, 2 replies; 36+ messages in thread
From: Stefan Monnier @ 2005-03-07  1:32 UTC (permalink / raw)
  To: caml-list

> In most cases you probably won't care when a file is closed after writing to
> it, so you can just rely on the garbage collector.

Very bad practice in (e.g.) an NFS world where the filesystem makes no
guarantee about file writes until you actually close the file.


        Stefan


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07  1:32   ` Stefan Monnier
@ 2005-03-07  2:48     ` Brian Hurt
  2005-03-07 13:30     ` Jon Harrop
  1 sibling, 0 replies; 36+ messages in thread
From: Brian Hurt @ 2005-03-07  2:48 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: caml-list

On Sun, 6 Mar 2005, Stefan Monnier wrote:

> > In most cases you probably won't care when a file is closed after writing to
> > it, so you can just rely on the garbage collector.
> 
> Very bad practice in (e.g.) an NFS world where the filesystem makes no
> guarantee about file writes until you actually close the file.

Ocaml does give you the close_out function to explicitly close an I/O 
stream.  Closing on GC collection just catches the odd cases, like exiting 
the function unexpected (via an exception, for example).

Brian



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] exception safety / RAII ?
  2005-03-07  0:03 ` Jon Harrop
  2005-03-07  1:32   ` Stefan Monnier
@ 2005-03-07  3:31   ` Michael Walter
  1 sibling, 0 replies; 36+ messages in thread
From: Michael Walter @ 2005-03-07  3:31 UTC (permalink / raw)
  To: Jon Harrop; +Cc: caml-list

On Mon, 7 Mar 2005 00:03:52 +0000, Jon Harrop <jon@jdh30.plus.com> wrote:
> > The C++ solution to this problem
> > is a technique called Resource Acquisition Is Initialization.
> 
> This is a poor man's alternative to garbage collection. The principal problem
> is the inability to determine what object owns which resources at any given
> point in the code.

I'm not sure one should think of it as a "poor man's" solution or an
"alternative to GC". An indication to that could be the inclusion of
"using" into C#. Another indication could be the inelegance of
finalizers (or as well the trouble people seem to have using them -- I
wouldn't blame a wrong (read: C++) context as a cause for that).

Michael


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07  1:32   ` Stefan Monnier
  2005-03-07  2:48     ` [Caml-list] " Brian Hurt
@ 2005-03-07 13:30     ` Jon Harrop
  2005-03-07 14:37       ` Stefan Monnier
                         ` (2 more replies)
  1 sibling, 3 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-07 13:30 UTC (permalink / raw)
  To: caml-list

On Monday 07 March 2005 01:32, Stefan Monnier wrote:
> > In most cases you probably won't care when a file is closed after writing
> > to it, so you can just rely on the garbage collector.
>
> Very bad practice in (e.g.) an NFS world where the filesystem makes no
> guarantee about file writes until you actually close the file.

Yes, this may go wrong under certain circumstances (it is not a guarantee) but 
I very rarely have problems with this.

On Monday 07 March 2005 03:31, Michael Walter wrote:
> I'm not sure one should think of it as a "poor man's" solution or an
> "alternative to GC". An indication to that could be the inclusion of
> "using" into C#.

I don't know C#, but when would you want to deallocate a resource before all 
references to it have disappeared?

> Another indication could be the inelegance of 
> finalizers (or as well the trouble people seem to have using them -- I
> wouldn't blame a wrong (read: C++) context as a cause for that).

How are finalisers inelegant? Apart from referencing an object from its own 
finaliser, what problems do people have?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: exception safety / RAII ?
  2005-03-07 13:30     ` Jon Harrop
@ 2005-03-07 14:37       ` Stefan Monnier
  2005-03-07 17:10         ` [Caml-list] " Jon Harrop
  2005-03-07 15:21       ` [Caml-list] " Michael Walter
  2005-03-08 21:32       ` [Caml-list] " Oliver Bandel
  2 siblings, 1 reply; 36+ messages in thread
From: Stefan Monnier @ 2005-03-07 14:37 UTC (permalink / raw)
  To: caml-list

>> Very bad practice [...]
[...]
> I very rarely have problems with this.

Very rarely having problems with something can't save it from being
a very bad practice.  Not explicitly closing your files is (in 99% of the
cases) just sloppy coding.  Kinda like letting a GC finalizer close
your windows: when the effect is visible from outside the process it
shouldn't be done in a finalizer.


        Stefan


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07 13:30     ` Jon Harrop
  2005-03-07 14:37       ` Stefan Monnier
@ 2005-03-07 15:21       ` Michael Walter
       [not found]         ` <200503071729.20117.jon@jdh30.plus.com>
  2005-03-08 21:32       ` [Caml-list] " Oliver Bandel
  2 siblings, 1 reply; 36+ messages in thread
From: Michael Walter @ 2005-03-07 15:21 UTC (permalink / raw)
  To: Jon Harrop; +Cc: caml-list

On Mon, 7 Mar 2005 13:30:48 +0000, Jon Harrop <jon@jdh30.plus.com> wrote:
> > I'm not sure one should think of it as a "poor man's" solution or an
> > "alternative to GC". An indication to that could be the inclusion of
> > "using" into C#.
> 
> I don't know C#, but when would you want to deallocate a resource before all
> references to it have disappeared?

I never had such a desire.

> > Another indication could be the inelegance of
> > finalizers (or as well the trouble people seem to have using them -- I
> > wouldn't blame a wrong (read: C++) context as a cause for that).
> 
> How are finalisers inelegant? Apart from referencing an object from its own
> finaliser, what problems do people have?

Referencing other objects from a finalizer.

Michael


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07 14:37       ` Stefan Monnier
@ 2005-03-07 17:10         ` Jon Harrop
  2005-03-08 13:07           ` Damien Doligez
                             ` (2 more replies)
  0 siblings, 3 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-07 17:10 UTC (permalink / raw)
  To: caml-list

On Monday 07 March 2005 14:37, Stefan Monnier wrote:
> > I very rarely have problems with this.
>
> Very rarely having problems with something can't save it from being
> a very bad practice.  Not explicitly closing your files is (in 99% of the
> cases) just sloppy coding.

If we're talking about programs which are expected to run for an arbitrary 
amount of time (servers, the top-level etc.) then yes.

However, many programs run for a short time and, in these cases, I believe 
that OCaml guarantees to close your files at least upon program termination, 
if not before. Therefore, I would say that implicitly deallocating external 
resources is not sloppy coding in general.

> Kinda like letting a GC finalizer close 
> your windows: when the effect is visible from outside the process it
> shouldn't be done in a finalizer.

The term "visible" in this context is subjective. People could look to see 
when you close your file, or they could make other measurements to determine 
whether or not you had deallocated an external resource, but unless this is 
likely to cause a problem I wouldn't worry.

In the case of closing windows, I agree that would be sloppy coding. If you 
were talking about resources which the window had required and which the 
window manager is not likely to run out of, I wouldn't call it sloppy coding.

In the case of lablGL not guaranteeing that OpenGL and context resources are 
deallocated in the proper order, this has never caused a problem for anyone 
AFAIK and it would be tricky to fix so I don't worry about. I'd like to fix 
it, yes, but it isn't at the top of my priority list because it doesn't cause 
a problem.

In the case of me implicitly deallocating OpenGL display lists, this is never 
likely to cause a problem in practice so I'll probably never have to worry 
about. A user could still determine that I don't deallocate them immediately 
though, so you could still say that it is "visible".

I also think that this discussion ties in with OCaml and soft real-time tasks. 
In theory, OCaml should not be good for such tasks because the GC could act 
unpredictably. In practice, I find that OCaml is perfectly good for soft 
real-time.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
       [not found]         ` <200503071729.20117.jon@jdh30.plus.com>
@ 2005-03-07 18:47           ` Michael Walter
  2005-03-08  1:10             ` Jon Harrop
  2005-03-08 11:33             ` [Caml-list] " Ville-Pertti Keinonen
  0 siblings, 2 replies; 36+ messages in thread
From: Michael Walter @ 2005-03-07 18:47 UTC (permalink / raw)
  To: caml-list, Jon Harrop

On Mon, 7 Mar 2005 17:29:19 +0000, Jon Harrop <jon@jdh30.plus.com> wrote:
> On Monday 07 March 2005 15:21, Michael Walter wrote:
> > On Mon, 7 Mar 2005 13:30:48 +0000, Jon Harrop <jon@jdh30.plus.com> wrote:
> > > I don't know C#, but when would you want to deallocate a resource before
> > > all references to it have disappeared?
> >
> > I never had such a desire.
> 
> Would you mind elaborating a little on what you do desire, i.e. what does
> "using" do in C#, when would you use it and how does this relate to OCaml?

Sure. I hope the following answers all three questions at once:

let using resource thunk =
  try
    let
      result = thunk resource
    in
      dispose resource;
      result
  with
   any_exception ->
     dispose resource;
     raise any_exception

My O'Caml is not very fluent, possible "dispose resource" should read
"resource # dispose". Basically, the idea is to deterministically
clean up resources, as early as possible (yes, "but it's not as early
as possible" is besides the point :-). In my experience this
simplifies resource management and reasoning about it.

> Presumably this is only difficult in the more complicated case of a general
> dependency graph between objects? In particular, one which has cycles. What
> kinds of programs require such sophistication?
I have no idea about with finalizers in O'Caml (hence my more
broad/general statement), but in other languages I've worked with
there are several limitations which all basically origin in the fact
that finalization order in these languages was non-deterministic.

Greetings,
Michael


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07 18:47           ` Michael Walter
@ 2005-03-08  1:10             ` Jon Harrop
  2005-03-08 22:19               ` Oliver Bandel
  2005-03-08 22:53               ` Daniel Yokomizo
  2005-03-08 11:33             ` [Caml-list] " Ville-Pertti Keinonen
  1 sibling, 2 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-08  1:10 UTC (permalink / raw)
  To: caml-list

On Monday 07 March 2005 18:47, Michael Walter wrote:
> On Mon, 7 Mar 2005 17:29:19 +0000, Jon Harrop <jon@jdh30.plus.com> wrote:
> > Would you mind elaborating a little on what you do desire, i.e. what does
> > "using" do in C#, when would you use it and how does this relate to
> > OCaml?
>
> Sure. I hope the following answers all three questions at once:
>
> let using resource thunk =
>   try
>     let
>       result = thunk resource
>     in
>       dispose resource;
>       result
>   with
>    any_exception ->
>      dispose resource;
>      raise any_exception
>
> My O'Caml is not very fluent, possible "dispose resource" should read
> "resource # dispose".

Either is clear enough.

> Basically, the idea is to deterministically 
> clean up resources, as early as possible (yes, "but it's not as early
> as possible" is besides the point :-). In my experience this
> simplifies resource management and reasoning about it.

Yes, so you can use your code to do this in OCaml. My concerns with such code 
basically revolve around the possibility of incorrectly deallocating an 
external resource and then using it again. This is not possible if you rely 
on the GC but, as you say, the problem is then the lack of guarantees about 
when resources have been deallocated by what point in the code.

Perhaps explicitly asking the GC to deallocate all such resources is a better 
solution? Depending on the circumstances, this could give a big performance 
hit though...

> > Presumably this is only difficult in the more complicated case of a
> > general dependency graph between objects? In particular, one which has
> > cycles. What kinds of programs require such sophistication?
>
> I have no idea about with finalizers in O'Caml (hence my more
> broad/general statement), but in other languages I've worked with
> there are several limitations which all basically origin in the fact
> that finalization order in these languages was non-deterministic.

Ok, I have found that, with a little thought and careful design beforehand, 
this is not a problem in OCaml. In the case of DAG dependency graphs, my 
solution is to represent the dependency graph for the GC by maintaining a 
list of references to dependees in each object. This forces the GC to respect 
dependencies when collecting.

If the dependency graph is allowed to contain cycles then this might not work. 
I'm not sure though.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07 18:47           ` Michael Walter
  2005-03-08  1:10             ` Jon Harrop
@ 2005-03-08 11:33             ` Ville-Pertti Keinonen
  2005-03-08 12:32               ` Richard Jones
  2005-03-08 18:28               ` Jon Harrop
  1 sibling, 2 replies; 36+ messages in thread
From: Ville-Pertti Keinonen @ 2005-03-08 11:33 UTC (permalink / raw)
  To: Michael Walter; +Cc: caml-list, Jon Harrop

On Mon, 2005-03-07 at 13:47 -0500, Michael Walter wrote:

> My O'Caml is not very fluent, possible "dispose resource" should read
> "resource # dispose". Basically, the idea is to deterministically
> clean up resources, as early as possible (yes, "but it's not as early
> as possible" is besides the point :-). In my experience this
> simplifies resource management and reasoning about it.

You're right, what you describe is often a good way of managing
resources and also standard practice in e.g. Common Lisp (your "using"
function looks a bit like unwind-protect).

In OCaml you need to know what function to use for disposal of the
specific kind of resource.  For the most general approach, you can pass
a function to call in order to dispose of the resource (making it even
more like unwind-protect).

> I have no idea about with finalizers in O'Caml (hence my more
> broad/general statement), but in other languages I've worked with
> there are several limitations which all basically origin in the fact
> that finalization order in these languages was non-deterministic.

This is also true in OCaml.

The current languages that I'm aware of in which people rely on
deterministic finalization are Python and Visual Basic.  In both cases,
it places nasty limitations on the implementation.

IMHO currently the closest to the "best of both worlds" is a good
garbage collector (with non-deterministic finalization) and explicit
management for those resources that need them (file handles are a good
example; in addition to the reasons already mentioned in this thread,
also because they may refer to sockets and to avoid running into file
descriptor limits).

I'm not sure I understand Jon Harrop's concern about using resources
after they've been deallocated.  This has been addressed in the obvious
way (return errors for operations on remaining references) in various
languages for decades, and unlike memory management and type errors,
AFAIK hasn't been a major source of bugs or complaints.



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-08 11:33             ` [Caml-list] " Ville-Pertti Keinonen
@ 2005-03-08 12:32               ` Richard Jones
  2005-03-08 14:17                 ` Michael Walter
  2005-03-08 18:28               ` Jon Harrop
  1 sibling, 1 reply; 36+ messages in thread
From: Richard Jones @ 2005-03-08 12:32 UTC (permalink / raw)
  To: caml-list

On Tue, Mar 08, 2005 at 01:33:12PM +0200, Ville-Pertti Keinonen wrote:
> IMHO currently the closest to the "best of both worlds" is a good
> garbage collector (with non-deterministic finalization) and explicit
> management for those resources that need them (file handles are a good
> example; in addition to the reasons already mentioned in this thread,
> also because they may refer to sockets and to avoid running into file
> descriptor limits).

I think it'd be nice to have both finalisation and destructors when a
local variable goes out of scope.  You might need to mark variables
specially to indicate that those (and only those) should be reference
counted.  I understand that the implementation would be non-trivial.
Perhaps:

  val open_in : string -> in_channel refcounted

There was a great paper I read about a year ago all about how
finalisation and destruction are completely separate concepts.
Unfortunately I can't find it now ...

Rich.

-- 
Richard Jones, CTO Merjis Ltd.
Merjis - web marketing and technology - http://merjis.com
Team Notepad - intranets and extranets for business - http://team-notepad.com


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07 17:10         ` [Caml-list] " Jon Harrop
@ 2005-03-08 13:07           ` Damien Doligez
  2005-03-08 21:56           ` Oliver Bandel
  2005-03-09 14:48           ` Stefan Monnier
  2 siblings, 0 replies; 36+ messages in thread
From: Damien Doligez @ 2005-03-08 13:07 UTC (permalink / raw)
  To: caml-list


On Mar 7, 2005, at 18:10, Jon Harrop wrote:

> However, many programs run for a short time and, in these cases, I 
> believe
> that OCaml guarantees to close your files at least upon program 
> termination,

OCaml does no such thing.  The OS does.

-- Damien


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-08 12:32               ` Richard Jones
@ 2005-03-08 14:17                 ` Michael Walter
  0 siblings, 0 replies; 36+ messages in thread
From: Michael Walter @ 2005-03-08 14:17 UTC (permalink / raw)
  To: Richard Jones; +Cc: caml-list

On Tue, 8 Mar 2005 12:32:11 +0000, Richard Jones <rich@annexia.org> wrote:
> [...]
> 
> There was a great paper I read about a year ago all about how
> finalisation and destruction are completely separate concepts.
> Unfortunately I can't find it now ...

Might it be "Destructors, Finalizers, and Synchronization" by Hans
Boehm? IIRC that was really a nice paper.

Michael


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-08 11:33             ` [Caml-list] " Ville-Pertti Keinonen
  2005-03-08 12:32               ` Richard Jones
@ 2005-03-08 18:28               ` Jon Harrop
  2005-03-08 21:34                 ` Damien Doligez
  2005-03-09 15:05                 ` Stefan Monnier
  1 sibling, 2 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-08 18:28 UTC (permalink / raw)
  To: caml-list

On Tuesday 08 March 2005 11:33, Ville-Pertti Keinonen wrote:
> I'm not sure I understand Jon Harrop's concern about using resources
> after they've been deallocated.  This has been addressed in the obvious
> way (return errors for operations on remaining references) in various
> languages for decades, and unlike memory management and type errors,
> AFAIK hasn't been a major source of bugs or complaints.

A great deal of effort has been put into writing static verifiers to ensure 
correct use, in order to remove this class of run-time errors. So I think 
this is unquestionably a source of bugs.

Could it not be said that having a GC is a way to avoid such errors in the 
context of memory allocation and deallocation?

On Tuesday 08 March 2005 13:07, Damien Doligez wrote:
> On Mar 7, 2005, at 18:10, Jon Harrop wrote:
> > I believe that OCaml guarantees to close your files at least upon program
> > termination,
>
> OCaml does no such thing.  The OS does.

Yipes! In that case I take back what I said before and agree with Stefan - it 
is sloppy coding style to not explicitly close a file.

That seems most odd though. Is this for historical reasons - closing files was 
added long before object finalisers?

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07 13:30     ` Jon Harrop
  2005-03-07 14:37       ` Stefan Monnier
  2005-03-07 15:21       ` [Caml-list] " Michael Walter
@ 2005-03-08 21:32       ` Oliver Bandel
  2 siblings, 0 replies; 36+ messages in thread
From: Oliver Bandel @ 2005-03-08 21:32 UTC (permalink / raw)
  To: caml-list

On Mon, Mar 07, 2005 at 01:30:48PM +0000, Jon Harrop wrote:
> On Monday 07 March 2005 01:32, Stefan Monnier wrote:
> > > In most cases you probably won't care when a file is closed after writing
> > > to it, so you can just rely on the garbage collector.
> >
> > Very bad practice in (e.g.) an NFS world where the filesystem makes no
> > guarantee about file writes until you actually close the file.
> 
> Yes, this may go wrong under certain circumstances (it is not a guarantee) but 
> I very rarely have problems with this.

Building reliable programs on unreliable assumptions
will definitely yield to problems.
Not during development, not during tests, but when the software
finally is used. (Murphey....)
So, buying that piece of code.... and your customers will wish
they better had bought the product from the other company...

Ciao,
   Oliver


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-08 18:28               ` Jon Harrop
@ 2005-03-08 21:34                 ` Damien Doligez
  2005-03-09 15:05                 ` Stefan Monnier
  1 sibling, 0 replies; 36+ messages in thread
From: Damien Doligez @ 2005-03-08 21:34 UTC (permalink / raw)
  To: caml-list

On Mar 8, 2005, at 19:28, Jon Harrop wrote:

> That seems most odd though. Is this for historical reasons - closing 
> files was
> added long before object finalisers?

It was done after thinking hard about the question.  The answer is that
the "close" system call has several effects.  Resource deallocation is
one of these effects, but it's not the only one.  So when to close is
almost always a decision that must be made by the programmer, and we
don't want to encourage people to think otherwise.

And it would be ugly to have both explicit (close function) and implicit
(finalizer) closing of a file.

-- Damien


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-07 17:10         ` [Caml-list] " Jon Harrop
  2005-03-08 13:07           ` Damien Doligez
@ 2005-03-08 21:56           ` Oliver Bandel
  2005-03-09 13:34             ` Damien Doligez
  2005-03-09 14:48           ` Stefan Monnier
  2 siblings, 1 reply; 36+ messages in thread
From: Oliver Bandel @ 2005-03-08 21:56 UTC (permalink / raw)
  To: caml-list

On Mon, Mar 07, 2005 at 05:10:52PM +0000, Jon Harrop wrote:
> On Monday 07 March 2005 14:37, Stefan Monnier wrote:
> > > I very rarely have problems with this.
> >
> > Very rarely having problems with something can't save it from being
> > a very bad practice.  Not explicitly closing your files is (in 99% of the
> > cases) just sloppy coding.
> 
> If we're talking about programs which are expected to run for an arbitrary 
> amount of time (servers, the top-level etc.) then yes.
> 
> However, many programs run for a short time and, in these cases, I believe 
> that OCaml guarantees to close your files at least upon program termination, 
> if not before. Therefore, I would say that implicitly deallocating external 
> resources is not sloppy coding in general.
> 
> > Kinda like letting a GC finalizer close 
> > your windows: when the effect is visible from outside the process it
> > shouldn't be done in a finalizer.
> 
> The term "visible" in this context is subjective.
[...]

If we say "visible from an outer environment", then it is clear,
that this is really unfunctional programming style.

What you are suggesting here?
... => It's how to write programs that introduce side-effects in a statistical
manner and hoping on some subjective likeliehoods that all works well
for all the time.

So, why are you using and promoting functional programming style
(which yields to more safeness in programs), when on the other
side you are layzy in programming?

That is, where the difference is between lazy evaluation of a
programming language and lazy programmer's habbits!

Some people rely on Perl's reference counting and are happy without
"use strict", and others rely on OCaml's Garbage Collector and
are happy with "-unsafe"-option....


But be sure: to write good and reliable software means to rely
on *nothing*!

You can write crap software in *every* language, if you want to...

...and crap begins, where the programmer is to lazy to write
good code.

Good code menas: good readable/understandable/good documented,
  but also reliable because of "knowing what's going on",
which means: prefer functional style, not imperative (and the reason is:
imperative code has side-effects you can not always oversee and which yields
to *stochastical* behaviour ---> that's the same problem, what you
are introducing, when relying on the Garbage Collector instead
of writing good code!).

The advantages of FP will be diminished by your style of programming!


It's like

let const = ref 1 (* no likeliehood here *)
let baviour_of_your_program = ..... (* something wired*)

  let _ = Random.self_init ();
          
    baviour_of_your_program  const (Random.float 10000.0)

Ciao,
   Oliver


P.S.: I tried Random.float max_float and it seems to be always between
       1.<something> * 10^307 ...  1.<something> * 10^308
      Is this a problem of initialization, or a problem of the Random-algorithm,
      or a kind of strange (?) behaviour of a random walk?


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-08  1:10             ` Jon Harrop
@ 2005-03-08 22:19               ` Oliver Bandel
  2005-03-08 22:53               ` Daniel Yokomizo
  1 sibling, 0 replies; 36+ messages in thread
From: Oliver Bandel @ 2005-03-08 22:19 UTC (permalink / raw)
  To: caml-list

On Tue, Mar 08, 2005 at 01:10:21AM +0000, Jon Harrop wrote:
> On Monday 07 March 2005 18:47, Michael Walter wrote:
> > On Mon, 7 Mar 2005 17:29:19 +0000, Jon Harrop <jon@jdh30.plus.com> wrote:
> > > Would you mind elaborating a little on what you do desire, i.e. what does
> > > "using" do in C#, when would you use it and how does this relate to
> > > OCaml?
> >
> > Sure. I hope the following answers all three questions at once:
> >
> > let using resource thunk =
> >   try
> >     let
> >       result = thunk resource
> >     in
> >       dispose resource;
> >       result
> >   with
> >    any_exception ->
> >      dispose resource;
> >      raise any_exception
> >
> > My O'Caml is not very fluent, possible "dispose resource" should read
> > "resource # dispose".
> 
> Either is clear enough.
> 
> > Basically, the idea is to deterministically 
> > clean up resources, as early as possible (yes, "but it's not as early
> > as possible" is besides the point :-). In my experience this
> > simplifies resource management and reasoning about it.
> 
> Yes, so you can use your code to do this in OCaml. My concerns with such code 
> basically revolve around the possibility of incorrectly deallocating an 
> external resource and then using it again. This is not possible if you rely 
> on the GC but, as you say, the problem is then the lack of guarantees about 
> when resources have been deallocated by what point in the code.

Allocating ressources (here: "variables" or name-content-bindings)
is not a problem in  functional programming.

Such problems occur when using imperative style.

When using I/O then you work on imperative system's stuff,
like filehandles or simething, when e.g. using Unix-module.
Then you have to be careful, what you are doing.

But even when you use the buffered I/O then it is
linked to system ressources, which are imperative in nature.

This means: do not rely on the GC then!
Free ressources as soon as possible!

If you reuse a "variable" again in a functional
language then this does not yield to problems like
dangling pointers in C.

But nevertheless for example opening a directory to read it's contents
in a recursive function, that traverses a very long path with many subdirectories
(and maybe opening filhandles to all files in a directory)
may cause to problems.... even if the GC and the memory does not say
something abot it, the system may say, that there are no more filedescriptors
available...

Relying on the GC doe not help you to prevent problrms here.

Testing on directories with only a handful of files, nothing
goes wrong... but then used the software in "realworld",
it crashes... which in C means: writing coredump,
and in OCaml (if no internal bug yields to C-like bhaviour ;-))
menas an uncatched exception.


> 
> Perhaps explicitly asking the GC to deallocate all such resources is a better 
> solution? Depending on the circumstances, this could give a big performance 
> hit though...

Best solution, when regarding the filehandle-excample is:
open only if necessary and as late as possible
 (maybe think again about your algorithm in use)
and close as far as possible.

All, what you have to do in C or *ANY* other language
to write good code also applies to OCaml.

It may be a good style of programming to wrap every
imperative stuff (like file I/O) in an environment
that automatically allocates/deallocates the resources.

Something like Postscript's 
gsave/grestore
or that a tag like <mytag> must be closed with </mytag>
in XML-like code...
...so it also makes sense to do I/O only in an
environment of something like

open_ressource()
   (do_something()) 
close_ressource()


Writing wrappers seems not to be a big problem in a functional
language.

But maybe this Could be part oc OCaml++ or something like that ;-)


Maybe Haskell's I/O seems to be like that, but I'm not
such a Haskell expert and didn't explore Hashell's
I/O in detail.... (because I switched to OCaml before ;-))


Ciao,
   Oliver


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: Re: exception safety / RAII ?
  2005-03-08  1:10             ` Jon Harrop
  2005-03-08 22:19               ` Oliver Bandel
@ 2005-03-08 22:53               ` Daniel Yokomizo
  2005-03-09  1:21                 ` [Caml-list] " Jon Harrop
  2005-03-09 13:21                 ` Damien Doligez
  1 sibling, 2 replies; 36+ messages in thread
From: Daniel Yokomizo @ 2005-03-08 22:53 UTC (permalink / raw)
  To: caml-list


"Jon Harrop" <jon@jdh30.plus.com> escreveu na mensagem
news:200503080110.21839.jon@jdh30.plus.com...
> On Monday 07 March 2005 18:47, Michael Walter wrote:

[snip]

> > I have no idea about with finalizers in O'Caml (hence my more
> > broad/general statement), but in other languages I've worked with
> > there are several limitations which all basically origin in the fact
> > that finalization order in these languages was non-deterministic.
>
> Ok, I have found that, with a little thought and careful design
beforehand,
> this is not a problem in OCaml. In the case of DAG dependency graphs, my
> solution is to represent the dependency graph for the GC by maintaining a
> list of references to dependees in each object. This forces the GC to
respect
> dependencies when collecting.

AFAIK it doesn't force the GC to respect the dependencies. A object is
garbage if it can't be reached from any root references, it doesn't matter
if other garbage objects still reference it. So if we have:


ROOT -> A -> B -> C

D -> E -> F

G -> B

H -> C


the GC can collect any of [D, E, F, G, H], in any order it wants, because
they're all garbage. An incremental collector could collect first [F, G, H]
because they are (say) large objects, and don't recycle the memory for [D,
E] until the next collection.

IIUC the current OCaml GC implementation may exhibit such properties (i.e.
respect dependencies) but it isn't required to do so.

> If the dependency graph is allowed to contain cycles then this might not
work.
> I'm not sure though.
>
> -- 
> Dr Jon D Harrop, Flying Frog Consultancy Ltd.
> Objective CAML for Scientists
> http://www.ffconsultancy.com/products/ocaml_for_scientists




^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: Re: exception safety / RAII ?
  2005-03-08 22:53               ` Daniel Yokomizo
@ 2005-03-09  1:21                 ` Jon Harrop
  2005-03-09 13:21                 ` Damien Doligez
  1 sibling, 0 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-09  1:21 UTC (permalink / raw)
  To: caml-list

On Tuesday 08 March 2005 22:53, Daniel Yokomizo wrote:
> "Jon Harrop" <jon@jdh30.plus.com> escreveu na mensagem
> news:200503080110.21839.jon@jdh30.plus.com...
> > Ok, I have found that, with a little thought and careful design
> > beforehand, 
> > this is not a problem in OCaml. In the case of DAG dependency graphs, my
> > solution is to represent the dependency graph for the GC by maintaining a
> > list of references to dependees in each object. This forces the GC to
> > respect 
> > dependencies when collecting.
>
> AFAIK it doesn't force the GC to respect the dependencies. An object is 
> garbage if it can't be reached from any root references, it doesn't matter
> if other garbage objects still reference it.

Yes, thank you for the more formal description. :-)

Provided people want exactly this behaviour (which I do) then I believe that 
the approach I am using will work. You are quite right that this only 
respects dependencies between live objects and not between garbage objects.

I haven't come across any tasks which require more sophisticated GC trickery, 
but I've no doubt that such tasks exist. I can't think of a good general 
solution which doesn't basically require you to implement your own GC in 
OCaml (weak pointers, incremental etc.).

> IIUC the current OCaml GC implementation may exhibit such properties (i.e.
> respect dependencies) but it isn't required to do so.

Yes, the current GC may happen to deallocate things in the reverse of the 
order they were allocated in (this would explain why some things currently 
happen to work) but I've no idea if this really is the case.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: Re: exception safety / RAII ?
  2005-03-08 22:53               ` Daniel Yokomizo
  2005-03-09  1:21                 ` [Caml-list] " Jon Harrop
@ 2005-03-09 13:21                 ` Damien Doligez
  1 sibling, 0 replies; 36+ messages in thread
From: Damien Doligez @ 2005-03-09 13:21 UTC (permalink / raw)
  To: caml users

On Mar 8, 2005, at 23:53, Daniel Yokomizo wrote:

> AFAIK it doesn't force the GC to respect the dependencies. A object is
> garbage if it can't be reached from any root references, it doesn't 
> matter
> if other garbage objects still reference it. So if we have:
>
>
> ROOT -> A -> B -> C
>
> D -> E -> F
>
> G -> B
>
> H -> C
>
>
> the GC can collect any of [D, E, F, G, H], in any order it wants, 
> because
> they're all garbage. An incremental collector could collect first [F, 
> G, H]
> because they are (say) large objects, and don't recycle the memory for 
> [D,
> E] until the next collection.

As far as _collecting_ is concerned, the GC can do it in any order it 
wants,
and the current implementation is likely to do it in order of increasing
addresses (i.e. in some unpredictable order).

> IIUC the current OCaml GC implementation may exhibit such properties 
> (i.e.
> respect dependencies) but it isn't required to do so.

What I did specify and implement for 3.08 is the following:

If you call Gc.finalise on your values in the same order as they are
allocated, and if you don't introduce new depedencies afterward (with
assignments), then the finalisation functions will be called in the
right order (i.e. D before E before F, etc).

On the other hand, it means that a non-terminating finalisation function
must call Gc.finalise_release in order to let the GC run other
finalisation functions.

-- Damien


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-08 21:56           ` Oliver Bandel
@ 2005-03-09 13:34             ` Damien Doligez
  0 siblings, 0 replies; 36+ messages in thread
From: Damien Doligez @ 2005-03-09 13:34 UTC (permalink / raw)
  To: caml-list

On Mar 8, 2005, at 22:56, Oliver Bandel wrote:

> P.S.: I tried Random.float max_float and it seems to be always between
>        1.<something> * 10^307 ...  1.<something> * 10^308
>       Is this a problem of initialization, or a problem of the 
> Random-algorithm,
>       or a kind of strange (?) behaviour of a random walk?

I've seen some 10^306 too.  If you think about it, 99% of the reals
between 0 and 10^308 are in the 10^306..10^308 range.

But it's true that there is a "problem": roughly speaking, Random.float
simply takes a (uniformly distributed) real between 0 and 1, rounds it
to the nearest float, and multiplies by its argument.  So in your case
it will never return a number greater than 0 and smaller than
epsilon * max_float.

It's not clear what the spec should be anyway.  If you want a uniform
distribution on the real interval and rounding to the nearest float,
then the missing result range has a vanishingly small probability
anyway.  If you want a uniform distribution on the (finite) set of
floats in the interval, you will get really counter-intuitive results
and a function that cannot be used for physical simulations.

-- Damien


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: exception safety / RAII ?
  2005-03-07 17:10         ` [Caml-list] " Jon Harrop
  2005-03-08 13:07           ` Damien Doligez
  2005-03-08 21:56           ` Oliver Bandel
@ 2005-03-09 14:48           ` Stefan Monnier
  2005-03-09 16:19             ` [Caml-list] " Jon Harrop
  2 siblings, 1 reply; 36+ messages in thread
From: Stefan Monnier @ 2005-03-09 14:48 UTC (permalink / raw)
  To: caml-list

>> > I very rarely have problems with this.
>> Very rarely having problems with something can't save it from being
>> a very bad practice.  Not explicitly closing your files is (in 99% of the
>> cases) just sloppy coding.
> If we're talking about programs which are expected to run for an arbitrary 
> amount of time (servers, the top-level etc.) then yes.

This logic is routinely used in C to simply never call `free' because they
only run for a short time.  That's a textbook example of "sloppy coding".

>> Kinda like letting a GC finalizer close  your windows: when the effect is
>> visible from outside the process it shouldn't be done in a finalizer.
> The term "visible" in this context is subjective.

I wouldn't call it "subjective", but it is indeed relative to a set of
assumptions about what is "visible" and what isn't.  My assumptions here are
generally that CPU-time and swap-space use are "invisible".  The CPU-time
part is mostly intrinsic in the fact that I write in a high-level language
on top of a multiuser OS and don't have any direct control over the actual
assembly code generated, nor over the scheduling decisions.  The swap-space
part is a basic assumption of a tracing GC.  They're not ideal assumptions,
but without them life is a lot more difficult.

In contrast "the content of my file when another NFS client tries to read it
20 seconds after I generated it (and got an ocamltop prompt back indicating
it'd been generated)" is something that I do consider as "externally
visible" because it doesn't make life much more difficult: just close the
file when you're done with it.  It's extremely rare that the point in the
code where a file can be closed is not trivial to find.


        Stefan


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: exception safety / RAII ?
  2005-03-08 18:28               ` Jon Harrop
  2005-03-08 21:34                 ` Damien Doligez
@ 2005-03-09 15:05                 ` Stefan Monnier
  2005-03-09 22:30                   ` [Caml-list] " Marcin 'Qrczak' Kowalczyk
  1 sibling, 1 reply; 36+ messages in thread
From: Stefan Monnier @ 2005-03-09 15:05 UTC (permalink / raw)
  To: caml-list

>> I'm not sure I understand Jon Harrop's concern about using resources
>> after they've been deallocated.  This has been addressed in the obvious
>> way (return errors for operations on remaining references) in various
>> languages for decades, and unlike memory management and type errors,
>> AFAIK hasn't been a major source of bugs or complaints.

> A great deal of effort has been put into writing static verifiers to ensure
> correct use, in order to remove this class of run-time errors.  So I think
> this is unquestionably a source of bugs.

There are different kinds of bugs.  They can be common/rare, serious/benign,
hard/easy to find, hard/easy to fix, ...
Errors that have to do with things like "close" are generally easy to fix.
It's important to catch them, so we have things like Vault that try to catch
them statically.

> Could it not be said that having a GC is a way to avoid such errors in the
> context of memory allocation and deallocation?

In contrast, errors that have to do with leakage and/or dangling pointers,
are often hard to fix, requiring a considerable rework of the code.

Having a GC gives you a freedom when designing an API that is completely
incomparable to the minor convenience of not having to explicitly
close files.  Compare the success of C++ destructors to deal with
file-closing and the insufficiency of those same destructors to deal with
object deallocation (leading to the never ending use of reference counting
and/or explicit copying).


        Stefan


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-09 14:48           ` Stefan Monnier
@ 2005-03-09 16:19             ` Jon Harrop
  2005-03-09 22:45               ` [Caml-list] Re: exception safety / RAII Oliver Bandel
  2005-03-10 14:33               ` exception safety / RAII ? Stefan Monnier
  0 siblings, 2 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-09 16:19 UTC (permalink / raw)
  To: caml-list

On Wednesday 09 March 2005 14:48, you wrote:
> >> Very rarely having problems with something can't save it from being
> >> a very bad practice.  Not explicitly closing your files is (in 99% of
> >> the cases) just sloppy coding.
> >
> > If we're talking about programs which are expected to run for an
> > arbitrary amount of time (servers, the top-level etc.) then yes.

My statements were based on the incorrect assumption that the OCaml GC closes 
files when it collects file handles. As this is not the case, I definitely 
agree with you that not explicitly closing files in OCaml is sloppy coding 
because they will not be closed implicitly.

However, provided you don't need to make any guarantees about when the file is 
closed during the running of the program, I still think that implicitly 
closing a file (or deallocating an external resource) via the GC is not 
sloppy coding. Indeed, this facility can be very useful and can eliminate an 
important class of run-time errors.

> This logic is routinely used in C to simply never call `free' because they
> only run for a short time.  That's a textbook example of "sloppy coding".

I wouldn't advocate never calling free() in a C program, but what is the 
difference between calling free at some unspecified point in the future and 
relying on a GC?

> It's extremely rare that the point in the code where a file can be closed is
> not trivial to find. 

In the case of files, yes. More generally, this can be applied to all sorts of 
external resources where that is not true.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-09 15:05                 ` Stefan Monnier
@ 2005-03-09 22:30                   ` Marcin 'Qrczak' Kowalczyk
  2005-03-10 14:20                     ` Stefan Monnier
  0 siblings, 1 reply; 36+ messages in thread
From: Marcin 'Qrczak' Kowalczyk @ 2005-03-09 22:30 UTC (permalink / raw)
  To: caml-list

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> Having a GC gives you a freedom when designing an API that is completely
> incomparable to the minor convenience of not having to explicitly
> close files.  Compare the success of C++ destructors to deal with
> file-closing and the insufficiency of those same destructors to deal with
> object deallocation (leading to the never ending use of reference counting
> and/or explicit copying).

The fact that GC is useful for freeing memory doesn't imply that we
should have no convenient way for closing files.

IMHO there should be something similar to C# 'using', especially given
that the GC will not close dropped files.

The current semantics of C# 'using' is not enough in the presence
of asynchronous exceptions. If OCaml wants to ever have reliable
asynchronous exceptions, its 'using' should have three distinguished
parts: acquire the resource, use it, and release it.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII
  2005-03-09 16:19             ` [Caml-list] " Jon Harrop
@ 2005-03-09 22:45               ` Oliver Bandel
  2005-03-09 23:42                 ` Charles Forsyth
  2005-03-10 14:33               ` exception safety / RAII ? Stefan Monnier
  1 sibling, 1 reply; 36+ messages in thread
From: Oliver Bandel @ 2005-03-09 22:45 UTC (permalink / raw)
  To: caml-list

On Wed, Mar 09, 2005 at 04:19:40PM +0000, Jon Harrop wrote:
> On Wednesday 09 March 2005 14:48, you wrote:
> > >> Very rarely having problems with something can't save it from being
> > >> a very bad practice.  Not explicitly closing your files is (in 99% of
> > >> the cases) just sloppy coding.
> > >
> > > If we're talking about programs which are expected to run for an
> > > arbitrary amount of time (servers, the top-level etc.) then yes.
> 
> My statements were based on the incorrect assumption that the OCaml GC closes 
> files when it collects file handles. As this is not the case, I definitely 
> agree with you that not explicitly closing files in OCaml is sloppy coding 
> because they will not be closed implicitly.
> 
> However, provided you don't need to make any guarantees about when the file is 
> closed during the running of the program, I still think that implicitly 
> closing a file (or deallocating an external resource) via the GC is not 
> sloppy coding. Indeed, this facility can be very useful and can eliminate an 
> important class of run-time errors.
> 
> > This logic is routinely used in C to simply never call `free' because they
> > only run for a short time.  That's a textbook example of "sloppy coding".
> 
> I wouldn't advocate never calling free() in a C program, but what is the 
> difference between calling free at some unspecified point in the future and 
> relying on a GC?

I'm not a GC-expert, but it seems obvious to me, that a GC frees
ressources at unspecified time and that also means at unspecified
time in respect to the code that is executed.

But calling a free() at a certain point in a program means that the
deallocation is done at a certain time (in respect to code
that is executed, even when not in certain real time in seconds).

So, a free() in C is not unspecified, as it is called at a certain
section of code.

The GC frees ressources not as long as they are in use, but
that they are not in use does not mean that they are *immediately* freed
by the GC.
It depends on statistical/stochastical things (not to determine).
And that's the difference.

To say a GC that it has to free ressources immediately,
something like a GC-free-flush or something like that
seems a littlebid like going back to free().
(Well, it's not the same, because the GC handles the
"references" of which values are needed and which are not needed
anymore, so a trigger to the GC to free ressources is not the same
as writing code in C that does a free()-call. But normally
it should be easier programming when the programmer does not necessarily
have to think about freeing of GC-ressources.... normally the
GC should be intelligent enough to handle it by itself.)

(Rare cases may be there, where it is necessary to invoke
 GC-specific functions.)

Ciao,
   Oliver


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII
  2005-03-09 22:45               ` [Caml-list] Re: exception safety / RAII Oliver Bandel
@ 2005-03-09 23:42                 ` Charles Forsyth
  0 siblings, 0 replies; 36+ messages in thread
From: Charles Forsyth @ 2005-03-09 23:42 UTC (permalink / raw)
  To: oliver, caml-list

>>I'm not a GC-expert, but it seems obvious to me, that a GC frees
>>ressources at unspecified time and that also means at unspecified
>>time in respect to the code that is executed.

i was going to keep out of this, but i suppose i won't.
	it seems obvious to me, that a GC frees
	resources at unspecified time
not necessarily: it is perfectly possible to define a language so as
to define as predictable those things that could be made predictable,
and then rely on that when programming.  that places the onus
on the implementation to do that, of course, and i suppose that
might result in inefficiency, but perhaps that can be traded off
against other things.  garbage collectors exist that can do that,
with reasonable efficiency in many contexts.
i've used for years a system that behaves
in just this way, and it works well, particularly when faults occur.

i'm not saying this approach is a universal panacea,
or that it's appropriate for caml, just that it is certainly feasible,
and it can work well in practice.  ``but will it work in theory?''
good question.


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: exception safety / RAII ?
  2005-03-09 22:30                   ` [Caml-list] " Marcin 'Qrczak' Kowalczyk
@ 2005-03-10 14:20                     ` Stefan Monnier
  0 siblings, 0 replies; 36+ messages in thread
From: Stefan Monnier @ 2005-03-10 14:20 UTC (permalink / raw)
  To: caml-list

> The fact that GC is useful for freeing memory doesn't imply that we
> should have no convenient way for closing files.

Agreed, I was only talking specifically about misuse of finalizers.


        Stefan


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: exception safety / RAII ?
  2005-03-09 16:19             ` [Caml-list] " Jon Harrop
  2005-03-09 22:45               ` [Caml-list] Re: exception safety / RAII Oliver Bandel
@ 2005-03-10 14:33               ` Stefan Monnier
  2005-03-10 16:52                 ` [Caml-list] " Jon Harrop
  1 sibling, 1 reply; 36+ messages in thread
From: Stefan Monnier @ 2005-03-10 14:33 UTC (permalink / raw)
  To: caml-list

> My statements were based on the incorrect assumption that the OCaml GC
> closes files when it collects file handles. As this is not the case,
> I definitely agree with you that not explicitly closing files in OCaml is
> sloppy coding because they will not be closed implicitly.

My argument stays the same either way.

> However, provided you don't need to make any guarantees about when the
> file is  closed during the running of the program, I still think that
> implicitly  closing a file (or deallocating an external resource) via the
> GC is not  sloppy coding. Indeed, this facility can be very useful and can
> eliminate an important class of run-time errors.

Can you give examples where it's useful?  I don't consider "not needing to
call `close' on line NNNN of my code" to be useful.

Can you describe the "important class of runtime errors" that would be
supposedly eliminated?

>> This logic is routinely used in C to simply never call `free' because they
>> only run for a short time.  That's a textbook example of "sloppy coding".
> I wouldn't advocate never calling free() in a C program, but what is the
> difference between calling free at some unspecified point in the future and
> relying on a GC?

When you rely on a GC, you don't need to keep the pointer around somewhere
in order to be able to call "free" on it and you don't have to keep track of
who might still be using the object.  This means that a library for
a collection data structure can have a very different interface since it
doesn't have to worry about ownership of the contents of the
data structure.

>> It's extremely rare that the point in the code where a file can be closed
>> is not trivial to find.
> In the case of files, yes.  More generally, this can be applied to all
> sorts of external resources where that is not true.

Might be: there's no way we can generalize.  I'm talking about files here.
Finalizers are great, but they shouldn't be used for files.

I'd also argue that they generally shouldn't be used for any "external
resource".  Though I wouldn't be surprised if there's a counter example
somewhere where I'd agree that finalizers are good solution for the
management of some particular kind of external resource in some
particular circumstance.


        Stefan


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-10 14:33               ` exception safety / RAII ? Stefan Monnier
@ 2005-03-10 16:52                 ` Jon Harrop
  2005-03-11 14:46                   ` Michael Walter
  2005-03-12 22:54                   ` Stefan Monnier
  0 siblings, 2 replies; 36+ messages in thread
From: Jon Harrop @ 2005-03-10 16:52 UTC (permalink / raw)
  To: caml-list

On Thursday 10 March 2005 14:33, Stefan Monnier wrote:
> > However, provided you don't need to make any guarantees about when the
> > file is  closed during the running of the program, I still think that
> > implicitly closing a file (or deallocating an external resource) via the
> > GC is not  sloppy coding. Indeed, this facility can be very useful and
> > can eliminate an important class of run-time errors.
>
> Can you give examples where it's useful?  I don't consider "not needing to
> call `close' on line NNNN of my code" to be useful.

OpenGL display lists from earlier in this thread.

> Can you describe the "important class of runtime errors" that would be
> supposedly eliminated?

In that case, undefined rendering behaviour when a display list is executed 
after it has been incorrectly destroyed. This could also wreck the OpenGL 
state and break rendering for the rest of the frame or even for the rest of 
the program.

Unless you go to great lengths to catch such errors in all cases (which could 
require arbitrarily complicated tests, slowing down your program) such 
mistakes could make an OCaml program segfault with more fragile external 
resources.

> > In the case of files, yes.  More generally, this can be applied to all
> > sorts of external resources where that is not true.
>
> Might be: there's no way we can generalize.  I'm talking about files here.
> Finalizers are great, but they shouldn't be used for files.

Let me try another file-specific example then: Programs which save output at 
some point during their execution. From the users point of view, there is no 
"visible" difference between having the program close the file as soon as 
writing is complete and leaving it up to the GC to close the file a short 
time afterwards (and before it completes). I have many such programs.

> I'd also argue that they generally shouldn't be used for any "external
> resource".  Though I wouldn't be surprised if there's a counter example
> somewhere where I'd agree that finalizers are good solution for the
> management of some particular kind of external resource in some
> particular circumstance.

Even if the external resource is memory?

Generally, I'd always consider exploiting the GC because of the safety it 
provides...

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [Caml-list] Re: exception safety / RAII ?
  2005-03-10 16:52                 ` [Caml-list] " Jon Harrop
@ 2005-03-11 14:46                   ` Michael Walter
  2005-03-12 22:54                   ` Stefan Monnier
  1 sibling, 0 replies; 36+ messages in thread
From: Michael Walter @ 2005-03-11 14:46 UTC (permalink / raw)
  To: Jon Harrop; +Cc: caml-list

On Thu, 10 Mar 2005 16:52:01 +0000, Jon Harrop <jon@ffconsultancy.com> wrote:
> > Can you give examples where it's useful?  I don't consider "not needing to
> > call `close' on line NNNN of my code" to be useful.
> 
> OpenGL display lists from earlier in this thread.

Typically you manage your rendering resources at well-defined points
in the life time of a program (for performance reasons -- for
performance reasons you probably also wouldn't use display lists, but
that is besides the point), so I don't see how this is a problem

> > > In the case of files, yes.  More generally, this can be applied to all
> > > sorts of external resources where that is not true.
> >
> > Might be: there's no way we can generalize.  I'm talking about files here.
> > Finalizers are great, but they shouldn't be used for files.
> 
> Let me try another file-specific example then: Programs which save output at
> some point during their execution. From the users point of view, there is no
> "visible" difference between having the program close the file as soon as
> writing is complete and leaving it up to the GC to close the file a short
> time afterwards (and before it completes). I have many such programs.

You might want to be able to process the output file as soon as it's
written, not as soon as the GC decides to close the file. Also,
wouldn't it be trivial to just implement it "the nice way" (maybe I
think of different cases where "programs [..] save output")?

Michael


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: exception safety / RAII ?
  2005-03-10 16:52                 ` [Caml-list] " Jon Harrop
  2005-03-11 14:46                   ` Michael Walter
@ 2005-03-12 22:54                   ` Stefan Monnier
  1 sibling, 0 replies; 36+ messages in thread
From: Stefan Monnier @ 2005-03-12 22:54 UTC (permalink / raw)
  To: caml-list

>> > However, provided you don't need to make any guarantees about when the
>> > file is  closed during the running of the program, I still think that
>> > implicitly closing a file (or deallocating an external resource) via the
>> > GC is not  sloppy coding. Indeed, this facility can be very useful and
>> > can eliminate an important class of run-time errors.
>> 
>> Can you give examples where it's useful?  I don't consider "not needing to
>> call `close' on line NNNN of my code" to be useful.

> OpenGL display lists from earlier in this thread.

Two problems with this example: it doesn't involve files AFAICT, and it's
not an example in any useful sense.  You'd need to describe the skeleton of
the code to explain why it's useful (rather than merely convenient).

>> Can you describe the "important class of runtime errors" that would be
>> supposedly eliminated?

> In that case, undefined rendering behaviour when a display list is executed
> after it has been incorrectly destroyed.  This could also wreck the OpenGL
> state and break rendering for the rest of the frame or even for the rest of
> the program.

[ Ignoring the fact that it still doesn't seem to involve files ] Are such
errors common (or difficult to diagnose/fix) enough that they deserve the
name "important class of runtime errors"? (genuine question: I know next to
nothing about OpenGL).

>> > In the case of files, yes.  More generally, this can be applied to all
>> > sorts of external resources where that is not true.
>> 
>> Might be: there's no way we can generalize.  I'm talking about files here.
>> Finalizers are great, but they shouldn't be used for files.

> Let me try another file-specific example then: Programs which save output
> at  some point during their execution.  From the users point of view,
> there is no  "visible" difference between having the program close the
> file as soon as  writing is complete and leaving it up to the GC to close
> the file a short  time afterwards (and before it completes).  I have many
> such programs.

You're arguing beside my point: I don't care whether there are cases where
using finalizers to close files doesn't hurt.  My point is both that there
are cases where they do hurt (even sometimes for the exact same code where
they didn't hurt in other circumstances), and that the added convenience of
not needing to explicitly close the file is insignificant.

So I'd like to see an example where the lack of a "file-close finalizer"
would make the code harder to write.

>> I'd also argue that they generally shouldn't be used for any "external
>> resource".  Though I wouldn't be surprised if there's a counter example
>> somewhere where I'd agree that finalizers are good solution for the
>> management of some particular kind of external resource in some
>> particular circumstance.
> Even if the external resource is memory?

I've already replied to this and even gave another example (CPU), so please
try something else.


        Stefan


^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2005-03-12 22:55 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-05 18:16 exception safety / RAII ? Michael Benfield
2005-03-05 18:44 ` [Caml-list] " Gerd Stolpmann
2005-03-07  0:03 ` Jon Harrop
2005-03-07  1:32   ` Stefan Monnier
2005-03-07  2:48     ` [Caml-list] " Brian Hurt
2005-03-07 13:30     ` Jon Harrop
2005-03-07 14:37       ` Stefan Monnier
2005-03-07 17:10         ` [Caml-list] " Jon Harrop
2005-03-08 13:07           ` Damien Doligez
2005-03-08 21:56           ` Oliver Bandel
2005-03-09 13:34             ` Damien Doligez
2005-03-09 14:48           ` Stefan Monnier
2005-03-09 16:19             ` [Caml-list] " Jon Harrop
2005-03-09 22:45               ` [Caml-list] Re: exception safety / RAII Oliver Bandel
2005-03-09 23:42                 ` Charles Forsyth
2005-03-10 14:33               ` exception safety / RAII ? Stefan Monnier
2005-03-10 16:52                 ` [Caml-list] " Jon Harrop
2005-03-11 14:46                   ` Michael Walter
2005-03-12 22:54                   ` Stefan Monnier
2005-03-07 15:21       ` [Caml-list] " Michael Walter
     [not found]         ` <200503071729.20117.jon@jdh30.plus.com>
2005-03-07 18:47           ` Michael Walter
2005-03-08  1:10             ` Jon Harrop
2005-03-08 22:19               ` Oliver Bandel
2005-03-08 22:53               ` Daniel Yokomizo
2005-03-09  1:21                 ` [Caml-list] " Jon Harrop
2005-03-09 13:21                 ` Damien Doligez
2005-03-08 11:33             ` [Caml-list] " Ville-Pertti Keinonen
2005-03-08 12:32               ` Richard Jones
2005-03-08 14:17                 ` Michael Walter
2005-03-08 18:28               ` Jon Harrop
2005-03-08 21:34                 ` Damien Doligez
2005-03-09 15:05                 ` Stefan Monnier
2005-03-09 22:30                   ` [Caml-list] " Marcin 'Qrczak' Kowalczyk
2005-03-10 14:20                     ` Stefan Monnier
2005-03-08 21:32       ` [Caml-list] " Oliver Bandel
2005-03-07  3:31   ` [Caml-list] " Michael Walter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).