caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Resource acquisition is initialization
@ 2002-12-11 19:19 Blair Zajac
  2002-12-11 19:55 ` Brian Hurt
  2002-12-12 13:15 ` Xavier Leroy
  0 siblings, 2 replies; 12+ messages in thread
From: Blair Zajac @ 2002-12-11 19:19 UTC (permalink / raw)
  To: Caml Users Mailing List

One of the nice things about C++ and Java is that with properly
designed classes, you don't need to worry about freeing resources
in complicated code, because the when the objects go out of scope
either normally or via an exception, they will clean themselves up.

Here's a good description of this idiom:

http://sourceforge.net/docman/display_doc.php?docid=8673&group_id=9028

Given that Ocaml has objects, it would be useful to have this
idiom available to us.  Is there a way to implement it, rather
than just waiting for the garbage collector?

Also, since objects have initializers, do they have finializers?  I
read the entire Oreilly book and didn't see any mention of them.

Reading the C code interface, it looks like you can associate a
finalizer function to clean up an abstract type, but can you do
this with normal Ocaml code?

Best,
Blair

-- 
Blair Zajac <blair@orcaware.com>
Plots of your system's performance - http://www.orcaware.com/orca/
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-11 19:19 [Caml-list] Resource acquisition is initialization Blair Zajac
@ 2002-12-11 19:55 ` Brian Hurt
  2002-12-12  0:27   ` Chet Murthy
                     ` (2 more replies)
  2002-12-12 13:15 ` Xavier Leroy
  1 sibling, 3 replies; 12+ messages in thread
From: Brian Hurt @ 2002-12-11 19:55 UTC (permalink / raw)
  To: Blair Zajac; +Cc: Caml Users Mailing List

On Wed, 11 Dec 2002, Blair Zajac wrote:

> One of the nice things about C++ and Java is that with properly
> designed classes, you don't need to worry about freeing resources
> in complicated code, because the when the objects go out of scope
> either normally or via an exception, they will clean themselves up.
> 
> Here's a good description of this idiom:
> 
> http://sourceforge.net/docman/display_doc.php?docid=8673&group_id=9028

I didn't think you could allocate objects on the stack in Java 
(fundamental types, like ints and booleans, yes- but not objects).

There are three problems I have with this idea.  The first problem is that
it greatly complicates exception handling, as now the exceptions have to
call destructors for all the objects on the stack as they pop the stack
frames off.  The second problem I have with this is what happens when an
object goes out of scope in it's original context, but isn't yet garbage?  
We've all seen C code like:

char * foo(...) {
    char buf[];
    /* do something to fill buf */
    return buf;
}

This sounds like a wonderful way to introduce dangling pointer bugs in the 
language.

Third, I question how usefull this idea is.  OK, so the resource doesn't 
get cleaned up the nanosecond it becomes garbage.  In most cases, this 
isn't a problem- for example, file handlers.  The fact that you have a 
couple of extra, garbage, filehandles open and not yet collected won't 
really hurt much of anything, so long as they get collected (and closed) 
eventually.  Most file objects come with an explicit close option, so even 
if you, for some unknown reason, write code that just sits in a tight loop 
opening files, you can close them just as fast and not leave lots of spare 
file descriptors open.  And Java provides a function to force a garbage 
collection, I beleive Ocaml does as well (in pervasives?  I'm still 
learning the language).

The only thing I can think of which cannot tolerate the cleanup slop is 
releasing a mutex.  Deleting the mutex itself is a good application for 
GC, unlocking the mutex is not.  And for that, I think representing 
holding the lock as the lifetime of an object to be a bad idea.  Were Caml 
interested more in doing multithreaded code, I'd recommend something like 
Java's synchronize keyword.

Brian

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-11 19:55 ` Brian Hurt
@ 2002-12-12  0:27   ` Chet Murthy
  2002-12-12  7:56   ` Alessandro Baretta
  2002-12-13  9:22   ` Mike Potanin
  2 siblings, 0 replies; 12+ messages in thread
From: Chet Murthy @ 2002-12-12  0:27 UTC (permalink / raw)
  To: Brian Hurt; +Cc: Blair Zajac, Caml Users Mailing List


Blair,

Perhaps, what you want is a "try_finally" for Ocaml.

E.g.

let finally f arg finf =
  let rv = try Inl(f arg) with e -> Inr e
  in (try finf arg (match rv with Inl v -> Some v | Inr _ -> None) with e -> ());
	match rv with
		Inl v -> v
	  | Inr e -> raise e

Now, while this code isn't the most efficient, I believe (haven't
checked the details) that with sufficient partial evaluation and some
code-rearranging which is semantics-preserving, this code becomes
efficient, albeit somewhat larger than perhaps entirely desirable.

--chet--
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-11 19:55 ` Brian Hurt
  2002-12-12  0:27   ` Chet Murthy
@ 2002-12-12  7:56   ` Alessandro Baretta
  2002-12-12 16:39     ` Brian Hurt
  2002-12-13  9:22   ` Mike Potanin
  2 siblings, 1 reply; 12+ messages in thread
From: Alessandro Baretta @ 2002-12-12  7:56 UTC (permalink / raw)
  To: Brian Hurt, Ocaml



Brian Hurt wrote:
> On Wed, 11 Dec 2002, Blair Zajac wrote:

> The only thing I can think of which cannot tolerate the cleanup slop is 
> releasing a mutex.  Deleting the mutex itself is a good application for 
> GC, unlocking the mutex is not.

It is not the GC which unlocks the mutex but the application 
code. See Mutex.unlock .

> And for that, I think representing 
> holding the lock as the lifetime of an object to be a bad idea.  Were Caml 
> interested more in doing multithreaded code, I'd recommend something like 
> Java's synchronize keyword.

What's the difference with respect to locking a Mutex?

Alex

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-11 19:19 [Caml-list] Resource acquisition is initialization Blair Zajac
  2002-12-11 19:55 ` Brian Hurt
@ 2002-12-12 13:15 ` Xavier Leroy
  2002-12-12 14:05   ` Dmitry Bely
                     ` (2 more replies)
  1 sibling, 3 replies; 12+ messages in thread
From: Xavier Leroy @ 2002-12-12 13:15 UTC (permalink / raw)
  To: Blair Zajac; +Cc: Caml Users Mailing List

> One of the nice things about C++ and Java is that with properly
> designed classes, you don't need to worry about freeing resources
> in complicated code, because the when the objects go out of scope
> either normally or via an exception, they will clean themselves up.

I believe this is a C++-specific idiom.  Java doesn't have
destructors, just finalizers that are called asynchronously by the
GC.  OCaml also has GC finalization (see below).

> Given that Ocaml has objects, it would be useful to have this
> idiom available to us.  Is there a way to implement it, rather
> than just waiting for the garbage collector?

Yes: higher-order functions.  For a file:

let with_file_in filename action =
  let ic = open_in filename in
  try
    let res = action ic in close_in ic; res
  with x ->
    close_in ic; raise x

For a mutex:

let synchronize mut action =
  try
    Mutex.lock mut;
    let res = action () in
    Mutex.unlock mut;
    res
  with x ->
    Mutex.unlock mut;
    raise x

You get the idea.

> Also, since objects have initializers, do they have finializers?  I
> read the entire Oreilly book and didn't see any mention of them.
> Reading the C code interface, it looks like you can associate a
> finalizer function to clean up an abstract type, but can you do
> this with normal Ocaml code?

Yes.  The function Gc.finalise lets you attach finalization code to any
heap-allocated Caml value, not just objects.  I'm not surprised it is
not mentioned in the O'Reilly book, since this is a recent addition to
the OCaml implementation.

- Xavier Leroy
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-12 13:15 ` Xavier Leroy
@ 2002-12-12 14:05   ` Dmitry Bely
  2002-12-12 14:16     ` Xavier Leroy
  2002-12-12 22:17   ` Quetzalcoatl Bradley
  2002-12-12 23:59   ` Blair Zajac
  2 siblings, 1 reply; 12+ messages in thread
From: Dmitry Bely @ 2002-12-12 14:05 UTC (permalink / raw)
  To: caml-list

Xavier Leroy <xavier.leroy@inria.fr> writes:

>> One of the nice things about C++ and Java is that with properly
>> designed classes, you don't need to worry about freeing resources
>> in complicated code, because the when the objects go out of scope
>> either normally or via an exception, they will clean themselves up.
>
> I believe this is a C++-specific idiom.  Java doesn't have
> destructors, just finalizers that are called asynchronously by the
> GC.  OCaml also has GC finalization (see below).
>
>> Given that Ocaml has objects, it would be useful to have this
>> idiom available to us.  Is there a way to implement it, rather
>> than just waiting for the garbage collector?
>
> Yes: higher-order functions.  For a file:
>
> let with_file_in filename action =
>   let ic = open_in filename in
>   try
>     let res = action ic in close_in ic; res
>   with x ->
>     close_in ic; raise x

Maybe I don't understand something but IMHO it's not very usable because
with_file_in type is fixed after the first use. So e.g. input_line and
input_char operation cannot be mixed. You cannot write something like

let process filename =
  let f = with_file_in filename in
     begin
       print_string (f input_line);
       print_char   (f input_char); (* syntax error! *)
     end

- Dmitry Bely


-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-12 14:05   ` Dmitry Bely
@ 2002-12-12 14:16     ` Xavier Leroy
  0 siblings, 0 replies; 12+ messages in thread
From: Xavier Leroy @ 2002-12-12 14:16 UTC (permalink / raw)
  To: Dmitry Bely; +Cc: caml-list

> Maybe I don't understand something but IMHO it's not very usable because
> with_file_in type is fixed after the first use. So e.g. input_line and
> input_char operation cannot be mixed. You cannot write something like
> 
> let process filename =
>   let f = with_file_in filename in
>      begin
>        print_string (f input_line);
>        print_char   (f input_char); (* syntax error! *)
>      end

Even without the typing problem, this would open and close the file
twice, which isn't what you want.  The correct usage is:

let process filename =
  with_file_in filename
    (fun ic ->
       print_string (input_line ic);
       print_char (input_char ic))

- Xavier Leroy
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-12  7:56   ` Alessandro Baretta
@ 2002-12-12 16:39     ` Brian Hurt
  0 siblings, 0 replies; 12+ messages in thread
From: Brian Hurt @ 2002-12-12 16:39 UTC (permalink / raw)
  To: Alessandro Baretta; +Cc: Brian Hurt, Ocaml

On Thu, 12 Dec 2002, Alessandro Baretta wrote:

> 
> 
> Brian Hurt wrote:
> > On Wed, 11 Dec 2002, Blair Zajac wrote:
> 
> > The only thing I can think of which cannot tolerate the cleanup slop is 
> > releasing a mutex.  Deleting the mutex itself is a good application for 
> > GC, unlocking the mutex is not.
> 
> It is not the GC which unlocks the mutex but the application 
> code. See Mutex.unlock .

Calling a function to unlock a mutex is precise- so long as you remember 
to always unlock the mutex.  At least, as I'm understanding things.  It's 
the difference between (in Java-esque):

    {
        mutex.lock();
        /* do stuff needing the mutex to be locked */
        mutex.unlock();
    }

and:
    {
        mutex_lock lock_obj = mutex.get_lock();
        /* do stuff needing the mutex to be locked */
    }
    /* lock_obj is now garbage- eventually the GC will clean it up, thus
     * unlocking the mutex.  But this may be a while.  Until that happens,
     * everyone still thinks we're holding the mutex locked.
     */

The problem with the first representation is that you can forget to unlock 
the mutex, especially on error paths.  Consider:
    {
        mutex.lock();
        /* do stuff */
        if (error) { throw AnException(); }
        /* Opps- did I just forget to unlock the mutex? */
        mutex.unlock();
    }

The problem with the second way is that you continue holding the lock for 
some indefinate amount of time until the GC frees the object.  This is 
what I meant by "the time you hold the lock is defined by the lifetime of 
an object".

Note that for most other resources, holding them a little too long isn't a 
problem.  Consider file handles, for example.  OK, you don't want to leak 
filehandles anymore than you want to leak memory, opening them and 
forgetting to ever close them.  But if a file handle stays open a little 
longer than you really need it to be, it's not a catastrophe.  There are 
generally enough spare handles that you can still open new files before 
all the old files get closed.  So the lag isn't critical.

> 
> > And for that, I think representing 
> > holding the lock as the lifetime of an object to be a bad idea.  Were Caml 
> > interested more in doing multithreaded code, I'd recommend something like 
> > Java's synchronize keyword.
> 
> What's the difference with respect to locking a Mutex?
> 

Java explicitly binds the time you hold a mutex to a certain code block- 
literally, a set of curly braces {} defines the length of time when you 
hold a lock.  When you leave that code block, via any means, the lock is 
automatically released.  So you have code like:

    synchronized(foo) {
        /* All the code in here has foo locked */
    }
    /* Code here has foo unlocked */

This is usefull because the programmer doesn't have to remember to unlock 
the mutex- the simple act of leaving the block automatically unlocks the 
mutex.  So:

    synchronized(foo) {
       if (error) throw AnException();
    }

isn't an error.  The throw will unlock the mutex on leaving the code 
block.  This does slow down exceptions a little- now you need to have a 
stack of locks to unlock as you throw the exception.  However this is way 
simpler to implement, and way faster, than having to keep track of all 
objects (and their types) on the stack and call the appropriate 
destructors as you unwind the stack.  And dealing with the corner cases 
implied (what happens when you throw an exception, which calls a 
destructor for an object on the stack, and that destructor throws another 
exception?).

This is the behavior I think was wanted- to bind the mutex lock to a 
specific peice of code.  I'd much rather do it explicitly, with a language 
extension, than a kludge which causes more problems than it solves.

Speaking of which, I've been noodling around with wether it's possible to 
implement synchronization automatically in the common case.  What objects 
need to have synchronization is easy to determine- those objects which can 
be reached from 2 or more threads need synchronization.  The question is, 
what synchronization.  Or how much.  Can you protect a whole slew of 
objects with a single lock?

Obviously, removing as much synchronization as possible is good for
performance.  Also, it's possible to construct examples where if multiple 
objects are protected by a single lock you don't have deadlock, while if 
the objects are each protected by their own lock deadlock is possible.

Brian


-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-12 13:15 ` Xavier Leroy
  2002-12-12 14:05   ` Dmitry Bely
@ 2002-12-12 22:17   ` Quetzalcoatl Bradley
  2002-12-12 23:59   ` Blair Zajac
  2 siblings, 0 replies; 12+ messages in thread
From: Quetzalcoatl Bradley @ 2002-12-12 22:17 UTC (permalink / raw)
  To: Caml Users Mailing List


On Thursday, December 12, 2002, at 05:15  AM, Xavier Leroy wrote:
> For a mutex:
>
> let synchronize mut action =
>   try
>     Mutex.lock mut;
>     let res = action () in
>     Mutex.unlock mut;
>     res
>   with x ->
>     Mutex.unlock mut;
>     raise x
>
> You get the idea.

For fun I try to use campl4 to add synchronize directive.

usage:   synchronize "expression that evaluates to Mutex.t" in 
"expression"
The value is result of "expression".

  Example:

let lock = Mutex.create ();;
let counter = ref 0;;
let next_sym prefix =
   synchronize lock in
     let current = !counter in
       counter := current + 1;
       prefix ^ (string_of_int current)
;;

synchronize.ml file:

open Pcaml;;

EXTEND
  expr: LEVEL "expr1"
   [[ "synchronize"; e1 = expr; "in"; e2 = expr ->
    <:expr<
     let __synchronize_lock = $e1$ in
     do {
      Mutex.lock __synchronize_lock;
     try
      let __synchronize_result = $e2$ in
      do { Mutex.unlock __synchronize_lock; __synchronize_result }
     with z ->
      do { Mutex.unlock __synchronize_lock; raise z }
     }
    >>
   ]];
END;;
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-12 13:15 ` Xavier Leroy
  2002-12-12 14:05   ` Dmitry Bely
  2002-12-12 22:17   ` Quetzalcoatl Bradley
@ 2002-12-12 23:59   ` Blair Zajac
  2 siblings, 0 replies; 12+ messages in thread
From: Blair Zajac @ 2002-12-12 23:59 UTC (permalink / raw)
  To: Xavier Leroy; +Cc: Caml Users Mailing List

Xavier Leroy wrote:
> 
> > One of the nice things about C++ and Java is that with properly
> > designed classes, you don't need to worry about freeing resources
> > in complicated code, because the when the objects go out of scope
> > either normally or via an exception, they will clean themselves up.
> 
> I believe this is a C++-specific idiom.  Java doesn't have
> destructors, just finalizers that are called asynchronously by the
> GC.  OCaml also has GC finalization (see below).
> 
> > Given that Ocaml has objects, it would be useful to have this
> > idiom available to us.  Is there a way to implement it, rather
> > than just waiting for the garbage collector?
> 
> Yes: higher-order functions.  For a file:
> 
> let with_file_in filename action =
>   let ic = open_in filename in
>   try
>     let res = action ic in close_in ic; res
>   with x ->
>     close_in ic; raise x
> 
> For a mutex:
> 
> let synchronize mut action =
>   try
>     Mutex.lock mut;
>     let res = action () in
>     Mutex.unlock mut;
>     res
>   with x ->
>     Mutex.unlock mut;
>     raise x
> 
> You get the idea.

Thanks for all the answers everybody sent, both on and off list, it's
much appreciated.

Best,
Blair

-- 
Blair Zajac <blair@orcaware.com>
Plots of your system's performance - http://www.orcaware.com/orca/
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-11 19:55 ` Brian Hurt
  2002-12-12  0:27   ` Chet Murthy
  2002-12-12  7:56   ` Alessandro Baretta
@ 2002-12-13  9:22   ` Mike Potanin
  2002-12-13 17:05     ` David Brown
  2 siblings, 1 reply; 12+ messages in thread
From: Mike Potanin @ 2002-12-13  9:22 UTC (permalink / raw)
  To: Brian Hurt; +Cc: Blair Zajac, Caml Users Mailing List

On Wed, 11 Dec 2002, Brian Hurt wrote:

> On Wed, 11 Dec 2002, Blair Zajac wrote:
> There are three problems I have with this idea.  The first problem is that
> it greatly complicates exception handling, as now the exceptions have to
> call destructors for all the objects on the stack as they pop the stack
> frames off.  The second problem I have with this is what happens when an
> object goes out of scope in it's original context, but isn't yet garbage?
> We've all seen C code like:
>
> char * foo(...) {
>     char buf[];
>     /* do something to fill buf */
>     return buf;
> }
>
> This sounds like a wonderful way to introduce dangling pointer bugs in the
> language.
Cyclone language handle this problec staticaly (compile time). It no need
GC use.

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] Resource acquisition is initialization
  2002-12-13  9:22   ` Mike Potanin
@ 2002-12-13 17:05     ` David Brown
  0 siblings, 0 replies; 12+ messages in thread
From: David Brown @ 2002-12-13 17:05 UTC (permalink / raw)
  To: Mike Potanin; +Cc: Brian Hurt, Blair Zajac, Caml Users Mailing List

On Fri, Dec 13, 2002 at 12:22:16PM +0300, Mike Potanin wrote:

> > char * foo(...) {
> >     char buf[];
> >     /* do something to fill buf */
> >     return buf;
> > }
> >
> > This sounds like a wonderful way to introduce dangling pointer bugs in the
> > language.

> Cyclone language handle this problec staticaly (compile time). It no need
> GC use.

Numerous languages handle this kind of construct.  Often, though, you
end up having to copy the result when you return.  However, they
wouldn't handle it if the function was defined to return a pointer.
Instead, however, they let functions return larger objects (such as
arrays).

Usually they are implemented with a secondary stack to hold these
values.

I suspect, though, that the additional copying that ends up happening
with the technique ends up being as, or more, expensive than Ocaml's
garbage collector, especially if the data doesn't live long and doesn't
survive the young area.

Dave Brown
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

end of thread, other threads:[~2002-12-13 17:05 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-12-11 19:19 [Caml-list] Resource acquisition is initialization Blair Zajac
2002-12-11 19:55 ` Brian Hurt
2002-12-12  0:27   ` Chet Murthy
2002-12-12  7:56   ` Alessandro Baretta
2002-12-12 16:39     ` Brian Hurt
2002-12-13  9:22   ` Mike Potanin
2002-12-13 17:05     ` David Brown
2002-12-12 13:15 ` Xavier Leroy
2002-12-12 14:05   ` Dmitry Bely
2002-12-12 14:16     ` Xavier Leroy
2002-12-12 22:17   ` Quetzalcoatl Bradley
2002-12-12 23:59   ` Blair Zajac

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