caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Scoped Bound Resource Management just for C++?
@ 2011-02-08 23:57 orbitz
  2011-02-09  0:46 ` Guillaume Yziquel
                   ` (5 more replies)
  0 siblings, 6 replies; 21+ messages in thread
From: orbitz @ 2011-02-08 23:57 UTC (permalink / raw)
  To: caml-list

One of the benefits, in my opinion, of C++ is SBRM.  You can reason  
about the lifetime of an object and have an give yourself guarantees  
about its clean up.  The method of initialization and clean up are  
also consistent for every object in the language.

My questions are:
1) Do other people in the FP world consider this to be a good strategy?
2) Can this be done in a sane way in a GCd language?
3) What are the alternatives in a language like Ocaml?

Thanks!


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-08 23:57 [Caml-list] Scoped Bound Resource Management just for C++? orbitz
@ 2011-02-09  0:46 ` Guillaume Yziquel
  2011-02-09  0:48 ` Jacques Garrigue
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 21+ messages in thread
From: Guillaume Yziquel @ 2011-02-09  0:46 UTC (permalink / raw)
  To: orbitz; +Cc: caml-list

Le Tuesday 08 Feb 2011 à 18:57:37 (-0500), orbitz@ezabel.com a écrit :
> One of the benefits, in my opinion, of C++ is SBRM.  You can reason
> about the lifetime of an object and have an give yourself guarantees
> about its clean up.  The method of initialization and clean up are
> also consistent for every object in the language.

I assume you're talking about destructions of temporaries and auto
variables in C++. To me, the main benefit of this appears when you're in
a procedurally oriented language and when the language idiom allows you
to pass your objects in registers when they are small enough, or relying
on compiler optimisations to avoid copying the objects over and over
between function calls. The downside is that as soon as you're crossing
boundaries between libraries or putting things on the freestore, there
is copying involved, and not-so-clear memory management semantics.

> My questions are:
> 1) Do other people in the FP world consider this to be a good
> strategy?

Not to my opinion. To me, the way OCaml manages the garbage collection
of the minor heap seems to me a more practical way of doing things and
not an inefficient one. Moreover, SBRM makes memory management semantics
not so easy to reason about when integrating C++ with an another
language or another runtime (callbacks from C++ for instance).

> 2) Can this be done in a sane way in a GCd language?

Nothing stops you from managing the lifecycle of your values
explicitely, but I do not think you'd reap the benefits above. Moreover,
from a GC point of view, I do not see how to implement an SBRM-friendly
scheme compatible with heap compacting GC algorithms like the modified
Cheney algorithm used in OCaml.

For integral types, you have SBRM quite for free in OCaml, but anything
more complex either gets optimised away if possible, or gets quickly
heap allocated (much more likely).

> 3) What are the alternatives in a language like Ocaml?

I think you would also have a typing issue in a language such as OCaml.
Having SBRM-managed values means not being able to constructs lists with
them or things like that. So each time you call a function with such a
value in parameter, you'd need the compiler to guarantee that it would
not try to heap allocate it. Otherwise, you're back with copying the
value.

I think your question depends on what kind of datatypes you're
interested in, what kind of lifecycle you expect from your values, and
what runtime benefits you expect of it.

If your value is short-lived, it is allocated on the minor heap, never
moves from there, and garbage collection of the minor heap is very fast.
That's the closest you can get, I guess. But you do not have guarantees
of it being garbage collected, unless you trigger manually garbage
collection of the minor heap (which may be costly if done in an
unreasonable manner).

> Thanks!


-- 
     Guillaume Yziquel


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-08 23:57 [Caml-list] Scoped Bound Resource Management just for C++? orbitz
  2011-02-09  0:46 ` Guillaume Yziquel
@ 2011-02-09  0:48 ` Jacques Garrigue
  2011-02-09  6:25 ` dmitry grebeniuk
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 21+ messages in thread
From: Jacques Garrigue @ 2011-02-09  0:48 UTC (permalink / raw)
  To: orbitz; +Cc: caml-list

On 2011/02/09, at 8:57, orbitz@ezabel.com wrote:

> One of the benefits, in my opinion, of C++ is SBRM.  You can reason about the lifetime of an object and have an give yourself guarantees about its clean up.  The method of initialization and clean up are also consistent for every object in the language.
> 
> My questions are:
> 1) Do other people in the FP world consider this to be a good strategy?
> 2) Can this be done in a sane way in a GCd language?
> 3) What are the alternatives in a language like Ocaml?

It is difficult to compare a manually managed language to a GCd language, a fortiori a functional one.
One first answer is that if your language is GCd you don't care about lifetime: the GC will clean up when needed anyway.
You may be concerned by when finalization occurs, but if your language is functional finalization cannot be observed, so you really don't care.
So I would say that you really don't think about these problems in most situations.
The only exceptions I see are:
* Memory leaks: have to be careful that you are not referencing dead data, preventing the GC from freeing it.
   This is a well known problem in Haskell, where you have lots of closure which can refer to huge amounts of data.
   This is much less a problem in ocaml, where most data structures do not contain closures,
    so you just have to be careful to design your data structures properly (you have to in any language...)
* Interaction with external world: explicitly managing objects outside of the ocaml heap.
   This is going to occur when you interface with a database, or with any external library or entity that manages large states.
   A good example is communicating with a GUI library.
   The GC API allows you to free data structures when they are no longer referenced by ocaml, but this may be too late
   (your application may not be calling the GC often enough, or you may have lurking references around)
   This is a situation where you might want to reason about object lifetime, but I'm not aware of tools to do that in ocaml.
   I don't know if SBRM (whatever it is) would help there.

Jacques Garrigue

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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-08 23:57 [Caml-list] Scoped Bound Resource Management just for C++? orbitz
  2011-02-09  0:46 ` Guillaume Yziquel
  2011-02-09  0:48 ` Jacques Garrigue
@ 2011-02-09  6:25 ` dmitry grebeniuk
  2011-02-09 12:01 ` rossberg
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 21+ messages in thread
From: dmitry grebeniuk @ 2011-02-09  6:25 UTC (permalink / raw)
  To: caml-list

> One of the benefits, in my opinion, of C++ is SBRM.  You can reason about
> the lifetime of an object and have an give yourself guarantees about its
> clean up.  The method of initialization and clean up are also consistent for
> every object in the language.


  I'm using with-idiom for managing external resources (90% of uses
of i/o channels, network connections, database connections), I find
it helpful.  With-function closes/frees resource when user-function
returns result or raises exception.
  A typical with-function can have a signature like:
val with_file_in_bin : string -> (in_channel -> 'a) -> 'a
  Of course, it's not safe in general case, since you can store
in_channel into some external reference or even return it, but I have
never made such mistakes (so far).


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-08 23:57 [Caml-list] Scoped Bound Resource Management just for C++? orbitz
                   ` (2 preceding siblings ...)
  2011-02-09  6:25 ` dmitry grebeniuk
@ 2011-02-09 12:01 ` rossberg
  2011-02-09 15:15   ` orbitz
  2011-02-09 19:11   ` Florian Weimer
  2011-02-09 18:03 ` Jon Harrop
  2011-02-09 20:47 ` Norman Hardy
  5 siblings, 2 replies; 21+ messages in thread
From: rossberg @ 2011-02-09 12:01 UTC (permalink / raw)
  To: orbitz; +Cc: caml-list

> One of the benefits, in my opinion, of C++ is SBRM.  You can reason
> about the lifetime of an object and have an give yourself guarantees
> about its clean up.  The method of initialization and clean up are
> also consistent for every object in the language.

Don't believe the hype. :) Scope-bound resource management is inherently
broken, at least without sophisticated type system support. In a
higher-order language, there are various ways in which objects could escape
their scope, e.g. closures, references, exceptions. That can only mean one
of two things for SBRM:

1) Either it is not actually true, i.e. life times are not actually bound by
scope in general and you have no actual guarantees,

2) or it is unsafe, i.e. you can access an object after its life time has
ended, with potentially desastrous effects.

C++ chose (2), which is out of the question for a safe language. If your
language makes heavy use of first-class functions (and thus closures) that
strategy is a particular no-go.

Also, SBRM does not scale at all to concurrency. The underlying assumption
that all life times are somehow well-bracketed through the dynamic calling
hierarchy simply doesn't hold anymore when you have shared-state
concurrency. Getting life times right in concurrent C++ is a nightmare in my
experience, and often requires synchronizing deallocation in quite
inefficient ways (thereby effectively making it explicit, and subverting the
whole idea of tying it to scope implicitly).

/Andreas


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 12:01 ` rossberg
@ 2011-02-09 15:15   ` orbitz
  2011-02-09 16:14     ` Gerd Stolpmann
  2011-02-10 10:39     ` Guillaume Yziquel
  2011-02-09 19:11   ` Florian Weimer
  1 sibling, 2 replies; 21+ messages in thread
From: orbitz @ 2011-02-09 15:15 UTC (permalink / raw)
  To: rossberg; +Cc: caml-list

Thanks for the answers everyone.

How does one safely write code in Ocaml that guarantees resources will  
be freed?  Guillaume mentioned the with-idiom, but even that doesn't  
seem entirely safe.

On Feb 9, 2011, at 7:01 AM, rossberg@mpi-sws.org wrote:

>> One of the benefits, in my opinion, of C++ is SBRM.  You can reason
>> about the lifetime of an object and have an give yourself guarantees
>> about its clean up.  The method of initialization and clean up are
>> also consistent for every object in the language.
>
> Don't believe the hype. :) Scope-bound resource management is  
> inherently
> broken, at least without sophisticated type system support. In a
> higher-order language, there are various ways in which objects could  
> escape
> their scope, e.g. closures, references, exceptions. That can only  
> mean one
> of two things for SBRM:
>
> 1) Either it is not actually true, i.e. life times are not actually  
> bound by
> scope in general and you have no actual guarantees,
>
> 2) or it is unsafe, i.e. you can access an object after its life  
> time has
> ended, with potentially desastrous effects.
>
> C++ chose (2), which is out of the question for a safe language. If  
> your
> language makes heavy use of first-class functions (and thus  
> closures) that
> strategy is a particular no-go.
>
> Also, SBRM does not scale at all to concurrency. The underlying  
> assumption
> that all life times are somehow well-bracketed through the dynamic  
> calling
> hierarchy simply doesn't hold anymore when you have shared-state
> concurrency. Getting life times right in concurrent C++ is a  
> nightmare in my
> experience, and often requires synchronizing deallocation in quite
> inefficient ways (thereby effectively making it explicit, and  
> subverting the
> whole idea of tying it to scope implicitly).
>
> /Andreas
>


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 15:15   ` orbitz
@ 2011-02-09 16:14     ` Gerd Stolpmann
  2011-02-09 16:52       ` David Rajchenbach-Teller
  2011-02-10 10:39     ` Guillaume Yziquel
  1 sibling, 1 reply; 21+ messages in thread
From: Gerd Stolpmann @ 2011-02-09 16:14 UTC (permalink / raw)
  To: orbitz; +Cc: rossberg, caml-list

Am Mittwoch, den 09.02.2011, 10:15 -0500 schrieb orbitz@ezabel.com:
> Thanks for the answers everyone.
> 
> How does one safely write code in Ocaml that guarantees resources will  
> be freed?  Guillaume mentioned the with-idiom, but even that doesn't  
> seem entirely safe.

You mean C++ is safer in this respect?

Come on. Fully automatic memory management as in Ocaml is certainly
safer than any semi-automatic scheme. It will find all memory blocks
that are not referenced anymore. It's guaranteed. It works even with
circular structures (this is not a boy GC).

You would use "with" only for cases where non-memory resources are
referenced, like file descriptors. And you have to close files in C++,
too. If you want to be very careful here, you can even set a finaliser
that emits a warning when you forgot to close a descriptor (but you have
then to remember whether you closed it), like in

type managed_fd =
  { fd : Unix.file_descr;
    mutable fd_closed : bool
  }

(* after opening the file: *)
let mfd = { fd=fd; fd_closed=false }

(* Attach the finaliser: *)
let mfd_fin mfd =
  if not mfd.fd_closed then
    prerr_endline "Hey, there is a forgotten file descriptor"
Gc.finalise mfd_fin mfd

(* Use mfd as in - ensure you always pass mfd around: *)
Unix.read mfd.fd ...

(* When you close: *)
Unix.close mfd.fd;
mfd.fd_closed <- true

I wouldn't recommend to close fd in mfd_fin, because fd might not be a
simple file, and you can trigger any kind of external activity by
closing it.

I've written a number of 24/7 server programs in Ocaml now, and I can
tell you, resource management is easy. You can usually skip the "search
for memory leaks" step before deploying to production.

Gerd

> On Feb 9, 2011, at 7:01 AM, rossberg@mpi-sws.org wrote:
> 
> >> One of the benefits, in my opinion, of C++ is SBRM.  You can reason
> >> about the lifetime of an object and have an give yourself guarantees
> >> about its clean up.  The method of initialization and clean up are
> >> also consistent for every object in the language.
> >
> > Don't believe the hype. :) Scope-bound resource management is  
> > inherently
> > broken, at least without sophisticated type system support. In a
> > higher-order language, there are various ways in which objects could  
> > escape
> > their scope, e.g. closures, references, exceptions. That can only  
> > mean one
> > of two things for SBRM:
> >
> > 1) Either it is not actually true, i.e. life times are not actually  
> > bound by
> > scope in general and you have no actual guarantees,
> >
> > 2) or it is unsafe, i.e. you can access an object after its life  
> > time has
> > ended, with potentially desastrous effects.
> >
> > C++ chose (2), which is out of the question for a safe language. If  
> > your
> > language makes heavy use of first-class functions (and thus  
> > closures) that
> > strategy is a particular no-go.
> >
> > Also, SBRM does not scale at all to concurrency. The underlying  
> > assumption
> > that all life times are somehow well-bracketed through the dynamic  
> > calling
> > hierarchy simply doesn't hold anymore when you have shared-state
> > concurrency. Getting life times right in concurrent C++ is a  
> > nightmare in my
> > experience, and often requires synchronizing deallocation in quite
> > inefficient ways (thereby effectively making it explicit, and  
> > subverting the
> > whole idea of tying it to scope implicitly).
> >
> > /Andreas
> >
> 
> 


-- 
------------------------------------------------------------
Gerd Stolpmann, Bad Nauheimer Str.3, 64289 Darmstadt,Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
Phone: +49-6151-153855                  Fax: +49-6151-997714
------------------------------------------------------------


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 16:14     ` Gerd Stolpmann
@ 2011-02-09 16:52       ` David Rajchenbach-Teller
  2011-02-09 17:54         ` orbitz
  0 siblings, 1 reply; 21+ messages in thread
From: David Rajchenbach-Teller @ 2011-02-09 16:52 UTC (permalink / raw)
  To: Gerd Stolpmann; +Cc: orbitz, rossberg, caml-list

Actually, in Batteries, we have to go through a number of hoops to be absolutely certain that a stream is flushed before we quit the application.
We have to interact with:
- users manually closing the stream;
- any of the downstream streams being closed for any reason;
- finalization;
- the programmer exiting the program with [exit];
- the user exiting the program with [Ctrl-C];
- ...

Of course, the same issues appear in C++.

Cheers,
 David

On Feb 9, 2011, at 5:14 PM, Gerd Stolpmann wrote:

> Am Mittwoch, den 09.02.2011, 10:15 -0500 schrieb orbitz@ezabel.com:
>> Thanks for the answers everyone.
>> 
>> How does one safely write code in Ocaml that guarantees resources will  
>> be freed?  Guillaume mentioned the with-idiom, but even that doesn't  
>> seem entirely safe.
> 
> You mean C++ is safer in this respect?
> 
> Come on. Fully automatic memory management as in Ocaml is certainly
> safer than any semi-automatic scheme. It will find all memory blocks
> that are not referenced anymore. It's guaranteed. It works even with
> circular structures (this is not a boy GC).
> 
> You would use "with" only for cases where non-memory resources are
> referenced, like file descriptors. And you have to close files in C++,
> too. If you want to be very careful here, you can even set a finaliser
> that emits a warning when you forgot to close a descriptor (but you have
> then to remember whether you closed it), like in
> 
> type managed_fd =
>  { fd : Unix.file_descr;
>    mutable fd_closed : bool
>  }
> 
> (* after opening the file: *)
> let mfd = { fd=fd; fd_closed=false }
> 
> (* Attach the finaliser: *)
> let mfd_fin mfd =
>  if not mfd.fd_closed then
>    prerr_endline "Hey, there is a forgotten file descriptor"
> Gc.finalise mfd_fin mfd
> 
> (* Use mfd as in - ensure you always pass mfd around: *)
> Unix.read mfd.fd ...
> 
> (* When you close: *)
> Unix.close mfd.fd;
> mfd.fd_closed <- true
> 
> I wouldn't recommend to close fd in mfd_fin, because fd might not be a
> simple file, and you can trigger any kind of external activity by
> closing it.
> 
> I've written a number of 24/7 server programs in Ocaml now, and I can
> tell you, resource management is easy. You can usually skip the "search
> for memory leaks" step before deploying to production.



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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 16:52       ` David Rajchenbach-Teller
@ 2011-02-09 17:54         ` orbitz
  2011-02-09 21:50           ` Jon Harrop
  2011-02-10  8:10           ` David Rajchenbach-Teller
  0 siblings, 2 replies; 21+ messages in thread
From: orbitz @ 2011-02-09 17:54 UTC (permalink / raw)
  To: David Rajchenbach-Teller; +Cc: Gerd Stolpmann, rossberg, caml-list

Do they appear in C++?  I would a dtor takes care of that for you when  
it comes to streams.


On Feb 9, 2011, at 11:52 AM, David Rajchenbach-Teller wrote:

> Actually, in Batteries, we have to go through a number of hoops to  
> be absolutely certain that a stream is flushed before we quit the  
> application.
> We have to interact with:
> - users manually closing the stream;
> - any of the downstream streams being closed for any reason;
> - finalization;
> - the programmer exiting the program with [exit];
> - the user exiting the program with [Ctrl-C];
> - ...
>
> Of course, the same issues appear in C++.
>
> Cheers,
> David
>
> On Feb 9, 2011, at 5:14 PM, Gerd Stolpmann wrote:
>
>> Am Mittwoch, den 09.02.2011, 10:15 -0500 schrieb orbitz@ezabel.com:
>>> Thanks for the answers everyone.
>>>
>>> How does one safely write code in Ocaml that guarantees resources  
>>> will
>>> be freed?  Guillaume mentioned the with-idiom, but even that doesn't
>>> seem entirely safe.
>>
>> You mean C++ is safer in this respect?
>>
>> Come on. Fully automatic memory management as in Ocaml is certainly
>> safer than any semi-automatic scheme. It will find all memory blocks
>> that are not referenced anymore. It's guaranteed. It works even with
>> circular structures (this is not a boy GC).
>>
>> You would use "with" only for cases where non-memory resources are
>> referenced, like file descriptors. And you have to close files in C+ 
>> +,
>> too. If you want to be very careful here, you can even set a  
>> finaliser
>> that emits a warning when you forgot to close a descriptor (but you  
>> have
>> then to remember whether you closed it), like in
>>
>> type managed_fd =
>> { fd : Unix.file_descr;
>>   mutable fd_closed : bool
>> }
>>
>> (* after opening the file: *)
>> let mfd = { fd=fd; fd_closed=false }
>>
>> (* Attach the finaliser: *)
>> let mfd_fin mfd =
>> if not mfd.fd_closed then
>>   prerr_endline "Hey, there is a forgotten file descriptor"
>> Gc.finalise mfd_fin mfd
>>
>> (* Use mfd as in - ensure you always pass mfd around: *)
>> Unix.read mfd.fd ...
>>
>> (* When you close: *)
>> Unix.close mfd.fd;
>> mfd.fd_closed <- true
>>
>> I wouldn't recommend to close fd in mfd_fin, because fd might not  
>> be a
>> simple file, and you can trigger any kind of external activity by
>> closing it.
>>
>> I've written a number of 24/7 server programs in Ocaml now, and I can
>> tell you, resource management is easy. You can usually skip the  
>> "search
>> for memory leaks" step before deploying to production.
>


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

* RE: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-08 23:57 [Caml-list] Scoped Bound Resource Management just for C++? orbitz
                   ` (3 preceding siblings ...)
  2011-02-09 12:01 ` rossberg
@ 2011-02-09 18:03 ` Jon Harrop
  2011-02-09 20:47 ` Norman Hardy
  5 siblings, 0 replies; 21+ messages in thread
From: Jon Harrop @ 2011-02-09 18:03 UTC (permalink / raw)
  To: orbitz, caml-list

Orbitz wrote:
> One of the benefits, in my opinion, of C++ is SBRM.  You can reason
> about the lifetime of an object and have an give yourself guarantees
> about its clean up.  The method of initialization and clean up are
> also consistent for every object in the language.
> 
> My questions are:
> 1) Do other people in the FP world consider this to be a good strategy?

For some kinds of resources under some circumstances, yes.

> 2) Can this be done in a sane way in a GCd language?

Yes, of course. You just use a higher order function to factor out the
pattern of initializing and cleaning up the resource. For example, the
following "file" function opens a file, applies the given function "f" to
the resulting channel and then closes the channel:

  let file name f =
    let ch = open_in name in
    try
      let x = f ch in
      close_in ch;
      x
    with e ->
      close_in ch
      raise e

The OOP equivalent is called the command pattern. On the .NET platform, this
pattern is provided by the IDisposable interface and languages like C# and
F# even include syntactic support for it. This is used to handle resources
that benefit from deterministic cleanup, like file handles.

> 3) What are the alternatives in a language like Ocaml?

The most obvious alternative is to leave clean up to the garbage collector
by using a finalizer. When the resource is either memory or equivalent to
memory, this works extremely well in practice and is simpler than manual
memory management. For example, I once used the garbage collector to clean
up OpenGL display lists. However, this is not generally advised for
non-memory resources because they tend to be much more precious and,
therefore, prone to being exhausted.

Cheers,
Jon.



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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 12:01 ` rossberg
  2011-02-09 15:15   ` orbitz
@ 2011-02-09 19:11   ` Florian Weimer
  2011-02-09 20:10     ` Andreas Rossberg
  1 sibling, 1 reply; 21+ messages in thread
From: Florian Weimer @ 2011-02-09 19:11 UTC (permalink / raw)
  To: rossberg; +Cc: orbitz, caml-list

> Scope-bound resource management is inherently broken, at least
> without sophisticated type system support.

If the environment supports communicating processes with separate
execution pointers, it is straightforward to bypass restrictions, no
matter how evolved the type system is.

> 2) or it is unsafe, i.e. you can access an object after its life time has
> ended, with potentially desastrous effects.

This can be made safe with type-safe memory and run-time checks.  I
don't think this is a good excuse.

In the end, this is about making it as easy as possible for
programmers to write resource-aware programs.  After all, the
challenge is that code without proper resource management seems to be
correct for small sample inputs, so problems are likely noticed only
much, much later.

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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 19:11   ` Florian Weimer
@ 2011-02-09 20:10     ` Andreas Rossberg
  2011-02-09 20:45       ` Florian Weimer
  0 siblings, 1 reply; 21+ messages in thread
From: Andreas Rossberg @ 2011-02-09 20:10 UTC (permalink / raw)
  To: OCaml List

On Feb 9, 2011, at 20.11 h, Florian Weimer wrote:

>> Scope-bound resource management is inherently broken, at least
>> without sophisticated type system support.
>
> If the environment supports communicating processes with separate
> execution pointers, it is straightforward to bypass restrictions, no
> matter how evolved the type system is.

I don't know what scenario you have in mind with "separate execution  
pointers". In principle, I'm pretty certain that you could always  
define some suitable (e.g. linear) type system, if your language was  
sufficiently well-behaved.

>> 2) or it is unsafe, i.e. you can access an object after its life  
>> time has
>> ended, with potentially desastrous effects.
>
> This can be made safe with type-safe memory and run-time checks.  I
> don't think this is a good excuse.

True, runtime checks can deal with some of the "disastrous effects",  
but they cannot make it safe in a broader sense (e.g., type-safe in an  
interesting way), and AFAICS don't apply to memory itself as a  
resource. You may argue that that is good enough, but then again, you  
can already achieve that level of assurance using higher-order  
functions.

/Andreas


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 20:10     ` Andreas Rossberg
@ 2011-02-09 20:45       ` Florian Weimer
  2011-02-09 21:12         ` Andreas Rossberg
  0 siblings, 1 reply; 21+ messages in thread
From: Florian Weimer @ 2011-02-09 20:45 UTC (permalink / raw)
  To: Andreas Rossberg; +Cc: OCaml List

* Andreas Rossberg:

> On Feb 9, 2011, at 20.11 h, Florian Weimer wrote:
>
>>> Scope-bound resource management is inherently broken, at least
>>> without sophisticated type system support.
>>
>> If the environment supports communicating processes with separate
>> execution pointers, it is straightforward to bypass restrictions, no
>> matter how evolved the type system is.
>
> I don't know what scenario you have in mind with "separate execution
> pointers". In principle, I'm pretty certain that you could always
> define some suitable (e.g. linear) type system, if your language was
> sufficiently well-behaved.

If you have coroutines or threads with communication among them, you
can always turn type-enforced region-based handles into open handles
with an explicit close operation.

>>> 2) or it is unsafe, i.e. you can access an object after its life
>>> time has
>>> ended, with potentially desastrous effects.
>>
>> This can be made safe with type-safe memory and run-time checks.  I
>> don't think this is a good excuse.
>
> True, runtime checks can deal with some of the "disastrous effects",
> but they cannot make it safe in a broader sense (e.g., type-safe in an
> interesting way), and AFAICS don't apply to memory itself as a
> resource.

Like array bounds checking, integer division or other partial
functions. 8-)

> You may argue that that is good enough, but then again, you can
> already achieve that level of assurance using higher-order
> functions.

This is mostly about syntax.  There is already a very convenient
notation, but it has a resource leak.

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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-08 23:57 [Caml-list] Scoped Bound Resource Management just for C++? orbitz
                   ` (4 preceding siblings ...)
  2011-02-09 18:03 ` Jon Harrop
@ 2011-02-09 20:47 ` Norman Hardy
  2011-02-09 21:00   ` Gabriel Scherer
  5 siblings, 1 reply; 21+ messages in thread
From: Norman Hardy @ 2011-02-09 20:47 UTC (permalink / raw)
  To: orbitz; +Cc: caml-list


On 2011 Feb 8, at 15:57 , orbitz@ezabel.com wrote:

> One of the benefits, in my opinion, of C++ is SBRM.  You can reason about the lifetime of an object and have an give yourself guarantees about its clean up.  The method of initialization and clean up are also consistent for every object in the language.
> 
> My questions are:
> 1) Do other people in the FP world consider this to be a good strategy?
> 2) Can this be done in a sane way in a GCd language?
> 3) What are the alternatives in a language like Ocaml?

Keykos was a platform intended for program agents from diverse and even hostile interests.
http://cap-lore.com/CapTheory/KK/
It had an adversarial space allocation technology.
http://cap-lore.com/CapTheory/KK/Space.html
It was an operating system with a space allocation facility that was both safer and less safe than GC.
It was safer in that it was feasible to write applications therein safe from space exhaustion.
It was less safe in that programming errors might delete space too soon.
It did not suffer, however, from ‘memory safety’ errors when ‘stale pointers’ were used.
The behavior of stale pointers was determined and ‘threw exceptions’ by default.
Lurking forgotten references that were indeed destined not to be used were not a problem as in GC.

Releasing storage was explicit and indeed an extra additional application burden.
It was also possible for the agent paying for the storage to reclaim the storage despite access by others.

The allocation mechanisms were responsible for space on timescales from milliseconds to years.

Many complex agreements on data access between parties, positive and negative, were possible in Keykos, and enforced by mutually trusted software agents therein.

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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 20:47 ` Norman Hardy
@ 2011-02-09 21:00   ` Gabriel Scherer
  0 siblings, 0 replies; 21+ messages in thread
From: Gabriel Scherer @ 2011-02-09 21:00 UTC (permalink / raw)
  To: Norman Hardy; +Cc: orbitz, caml-list

[-- Attachment #1: Type: text/plain, Size: 2989 bytes --]

For an example of a language with linear types for resource management, as
mentioned by Andreas Rossberg, see ATS : http://www.ats-lang.org/

Of particular interest to the present discussion are the following pages:
- Stack allocation :
http://www.ats-lang.org/TUTORIAL/contents/stack-allocation.html
  memory and closures are allocated on the stack, with the type system
guaranteeing that such values cannot be referenced after the current
function exit
- Cairo basics :
http://www.ats-lang.org/DOCUMENTATION/ATSCAIRO/HTML/c28.html
  a small tutorial for programming with the Cairo library; linear types are
used to track the cairo resources, which internally -- on the C side -- use
reference counting
- "Implementing Reliable Linux Device Drivers in ATS" :
http://www.ats-lang.org/PAPER/LDD-plpv07.pdf

On Wed, Feb 9, 2011 at 9:47 PM, Norman Hardy <norm@cap-lore.com> wrote:

>
> On 2011 Feb 8, at 15:57 , orbitz@ezabel.com wrote:
>
> > One of the benefits, in my opinion, of C++ is SBRM.  You can reason about
> the lifetime of an object and have an give yourself guarantees about its
> clean up.  The method of initialization and clean up are also consistent for
> every object in the language.
> >
> > My questions are:
> > 1) Do other people in the FP world consider this to be a good strategy?
> > 2) Can this be done in a sane way in a GCd language?
> > 3) What are the alternatives in a language like Ocaml?
>
> Keykos was a platform intended for program agents from diverse and even
> hostile interests.
> http://cap-lore.com/CapTheory/KK/
> It had an adversarial space allocation technology.
> http://cap-lore.com/CapTheory/KK/Space.html
> It was an operating system with a space allocation facility that was both
> safer and less safe than GC.
> It was safer in that it was feasible to write applications therein safe
> from space exhaustion.
> It was less safe in that programming errors might delete space too soon.
> It did not suffer, however, from ‘memory safety’ errors when ‘stale
> pointers’ were used.
> The behavior of stale pointers was determined and ‘threw exceptions’ by
> default.
> Lurking forgotten references that were indeed destined not to be used were
> not a problem as in GC.
>
> Releasing storage was explicit and indeed an extra additional application
> burden.
> It was also possible for the agent paying for the storage to reclaim the
> storage despite access by others.
>
> The allocation mechanisms were responsible for space on timescales from
> milliseconds to years.
>
> Many complex agreements on data access between parties, positive and
> negative, were possible in Keykos, and enforced by mutually trusted software
> agents therein.
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

[-- Attachment #2: Type: text/html, Size: 4014 bytes --]

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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 20:45       ` Florian Weimer
@ 2011-02-09 21:12         ` Andreas Rossberg
  2011-02-10 21:31           ` Florian Weimer
  0 siblings, 1 reply; 21+ messages in thread
From: Andreas Rossberg @ 2011-02-09 21:12 UTC (permalink / raw)
  To: OCaml List

On Feb 9, 2011, at 21.45 h, Florian Weimer wrote:
>>>> Scope-bound resource management is inherently broken, at least
>>>> without sophisticated type system support.
>>>
>>> If the environment supports communicating processes with separate
>>> execution pointers, it is straightforward to bypass restrictions, no
>>> matter how evolved the type system is.
>>
>> I don't know what scenario you have in mind with "separate execution
>> pointers". In principle, I'm pretty certain that you could always
>> define some suitable (e.g. linear) type system, if your language was
>> sufficiently well-behaved.
>
> If you have coroutines or threads with communication among them, you
> can always turn type-enforced region-based handles into open handles
> with an explicit close operation.

I still don't know what you are talking about. Why should a suitable  
type system not be able to make such an operation ill-typed?

>>>> 2) or it is unsafe, i.e. you can access an object after its life
>>>> time has
>>>> ended, with potentially desastrous effects.
>>>
>>> This can be made safe with type-safe memory and run-time checks.  I
>>> don't think this is a good excuse.
>>
>> True, runtime checks can deal with some of the "disastrous effects",
>> but they cannot make it safe in a broader sense (e.g., type-safe in  
>> an
>> interesting way), and AFAICS don't apply to memory itself as a
>> resource.
>
> Like array bounds checking, integer division or other partial
> functions. 8-)

Right. But these are examples of collateral damage of useful features,  
while the one under discussion is just the damage, with no new  
expressiveness to justify it. ;)

/Andreas


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

* RE: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 17:54         ` orbitz
@ 2011-02-09 21:50           ` Jon Harrop
  2011-02-10  8:10           ` David Rajchenbach-Teller
  1 sibling, 0 replies; 21+ messages in thread
From: Jon Harrop @ 2011-02-09 21:50 UTC (permalink / raw)
  To: orbitz; +Cc: caml-list

Orbitz:
> Do they appear in C++?

Yes.

> I would a dtor takes care of that for you when it comes to streams.

Only when the dtor is called. If a thread is aborted or exit or abort are
called then the dtor may not be called and your resource may leak.

> How does one safely write code in Ocaml that guarantees resources will be
freed?  

You cannot so you make the best of a bad job and write code that catches
most errors in practice, like the code I gave. You might also add a
syntactic construct like F#'s "use" binding that makes this even simpler and
clearer but, ultimately, it is still not perfect.

Cheers,
Jon.



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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 17:54         ` orbitz
  2011-02-09 21:50           ` Jon Harrop
@ 2011-02-10  8:10           ` David Rajchenbach-Teller
  1 sibling, 0 replies; 21+ messages in thread
From: David Rajchenbach-Teller @ 2011-02-10  8:10 UTC (permalink / raw)
  To: orbitz; +Cc: Gerd Stolpmann, rossberg, caml-list


Well, that depends -- keep in mind that I'm discussing one specific instance, that of closing streams and ensuring that they are correctly flushed, in the right order.

* users manually closing the stream
keeping things safe is essentially the same issue in OCaml and C++;

* downstream stream being closed
keeping things safe is essentially the same issue in OCaml and C++, but the garbage-collector does make things easier in OCaml;

* garbage-collection/deallocation
Probably easier in C++, as long as you keep to the small subset of C++ in which users discipline themselves to simple resource allocation/finalization idioms.
Suddenly much harder if your users can heap-allocate or pass by reference for the purpose of sharing between distinct scopes (which, in my experience, is the kind of thing you want to do as soon as your library is powerful enough).

* abrupt (but non-segfault) termination of the program, say a thread killing the whole process 
Now, I'm not sure how one would implement this in C++. I tend to believe it's easier in OCaml, as judicious use of [at_exit] and weak references lets you register behaviors that will only be triggered if garbage-collection hasn't taken place by the time the program exits.



Now, of course, we touch another issue: the way I see it, C++ is not just one language, but a whole collection of languages with interoperability. Things that make perfect sense and are completely safe if you limit yourself to some idioms suddenly become the stuff of segfaultish nightmares if you attempt to integrate them in a project which has been written with a distinct set of axioms. I'd call this a clear win by OCaml :)

Cheers,
 David

On Feb 9, 2011, at 6:54 PM, orbitz@ezabel.com wrote:

> Do they appear in C++?  I would a dtor takes care of that for you when it comes to streams.



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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 15:15   ` orbitz
  2011-02-09 16:14     ` Gerd Stolpmann
@ 2011-02-10 10:39     ` Guillaume Yziquel
  2011-02-10 10:59       ` Guillaume Yziquel
  1 sibling, 1 reply; 21+ messages in thread
From: Guillaume Yziquel @ 2011-02-10 10:39 UTC (permalink / raw)
  To: orbitz; +Cc: caml-list

Le Wednesday 09 Feb 2011 à 10:15:43 (-0500), orbitz@ezabel.com a écrit :
> Thanks for the answers everyone.
> 
> How does one safely write code in Ocaml that guarantees resources
> will be freed?  Guillaume mentioned the with-idiom, but even that
> doesn't seem entirely safe.

It was Dmitry Grebeniuk that mentioned it. Not me.

To me, the closest you can get is:

module type Resource = sig

	type t (* opaque type for mystuff. *)

	val v : t option ref

	val free : t -> unit

	(* Some functions manipulating type t, without storing
	 * type t values in any other structures such as lists.
	 * Should avoid anything that 'unopacifies' type t *)

end

let sbrm (x : (module Resource)) =
	let module R = (val x : Resource) in
	let do_stuff z =
		(* Write your code here *)
	in
	let Some w = !v in
	let return_value = do_stuff w in
	v := None;
	free w;
	return_value
	
let wrap_my_stuff (my_stuff : my_type) = (module struct

	type t = my_type

	let v = ref (Some my_stuff)

	(* Declarations of other functions *)

end : Resource)

Essentially, you put my_stuff into a first-class module, when calling
the sbrm function, the module is unpacked, and the type R.t is local to
the scope of the function sbrm. This forbids you to store the value in
the reference v anywhere else (excepts if you use existentialish-type stuff
like objects, first-class modules, or funky records). So you code your
do_stuff function under this typing constraints, when you're done, you
invalidate the reference v, and then free the w stuff, and then return
the value.

This code is glaringly unsatisfactory and inefficient. It's however the
only way I see of (mildly) forbiding at the type level to put the value
that is supposed to have a scope-bounded lifecycle somewhere else in the
heap that might tell the GC that it should live longer.

This also assumes that as soon as you create an object of mystuff, it is
immediately wrapped using wrap_my_stuff, and not used anywhere else.

The memory content of mystuff may live on, but it gets 'finalised' in
the scope of the sbrm function.

You still have issues with putting your stuff into existential types (I
do not think this can be avoided). And in the current state, this idiom
is error-prone. Could perhaps be lifted to a Camlp4 syntax extension
which would make it more 'robust'. Something like

opaque Resource = struct

	opaque type t = mytype

	(* manipulations of type t or of type 'mytype' that gets
	 * rewritten to 't' by Camlp4 *)

end

would generate the module type, the embedding of mytypes into
first-class modules, and the adequate sbrm function, together with an
sbrm keyword mimicking the with idiom.

Needless to say, the with- idiom is much more practical.

Otherwise you would need to refine the type system of OCaml to include
information as to whether an argument can be attached to another
datastructure inside a given function. I do not see why it could not be
done, but I do not see why it should be done.

-- 
     Guillaume Yziquel


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-10 10:39     ` Guillaume Yziquel
@ 2011-02-10 10:59       ` Guillaume Yziquel
  0 siblings, 0 replies; 21+ messages in thread
From: Guillaume Yziquel @ 2011-02-10 10:59 UTC (permalink / raw)
  To: orbitz; +Cc: caml-list

Le Thursday 10 Feb 2011 à 11:39:53 (+0100), Guillaume Yziquel a écrit :
> Le Wednesday 09 Feb 2011 à 10:15:43 (-0500), orbitz@ezabel.com a écrit :

And even with all that has been mentioned, there isn't really a way to
avoid the fact that closures may still hold on to your value. 

> Otherwise you would need to refine the type system of OCaml to include
> information as to whether an argument can be attached to another
> datastructure inside a given function. I do not see why it could not be
> done, but I do not see why it should be done.

That's perhaps the only way to avoid closures from holding to your
value, by forbidding partial evaluation, and enforcing full evaluation.

But that's way overkill.

-- 
     Guillaume Yziquel


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

* Re: [Caml-list] Scoped Bound Resource Management just for C++?
  2011-02-09 21:12         ` Andreas Rossberg
@ 2011-02-10 21:31           ` Florian Weimer
  0 siblings, 0 replies; 21+ messages in thread
From: Florian Weimer @ 2011-02-10 21:31 UTC (permalink / raw)
  To: Andreas Rossberg; +Cc: OCaml List

* Andreas Rossberg:

>> If you have coroutines or threads with communication among them, you
>> can always turn type-enforced region-based handles into open handles
>> with an explicit close operation.
>
> I still don't know what you are talking about. Why should a suitable
> type system not be able to make such an operation ill-typed?

It's a general problem.  Once you've got message passing, you've got
mutable state and the ability to escape regions.  Basically, you do
something like this:

  val resource = openResource params
  fun loop()
    (case receiveMailbox () of
       READ count => (read resource count; sendMailbox ACK; loop ())
       WRITE buffer => (write resource buffer; sendMailbox ACK; loop ())
       CLOSE => ())
  end
  val _ = loop ()
  val _ = close resource

>> Like array bounds checking, integer division or other partial
>> functions. 8-)
>
> Right. But these are examples of collateral damage of useful features,
> while the one under discussion is just the damage, with no new
> expressiveness to justify it. ;)

It's not about expressiveness, it's about making writing correct (that
is, resource-aware) code easier.

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

end of thread, other threads:[~2011-02-10 21:32 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-08 23:57 [Caml-list] Scoped Bound Resource Management just for C++? orbitz
2011-02-09  0:46 ` Guillaume Yziquel
2011-02-09  0:48 ` Jacques Garrigue
2011-02-09  6:25 ` dmitry grebeniuk
2011-02-09 12:01 ` rossberg
2011-02-09 15:15   ` orbitz
2011-02-09 16:14     ` Gerd Stolpmann
2011-02-09 16:52       ` David Rajchenbach-Teller
2011-02-09 17:54         ` orbitz
2011-02-09 21:50           ` Jon Harrop
2011-02-10  8:10           ` David Rajchenbach-Teller
2011-02-10 10:39     ` Guillaume Yziquel
2011-02-10 10:59       ` Guillaume Yziquel
2011-02-09 19:11   ` Florian Weimer
2011-02-09 20:10     ` Andreas Rossberg
2011-02-09 20:45       ` Florian Weimer
2011-02-09 21:12         ` Andreas Rossberg
2011-02-10 21:31           ` Florian Weimer
2011-02-09 18:03 ` Jon Harrop
2011-02-09 20:47 ` Norman Hardy
2011-02-09 21:00   ` Gabriel Scherer

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).