December 09, 2008 Re: Notes on Defective C++ | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jim Hewes | == Quote from Jim Hewes (jimhewes@gmail.com)'s article
> On that web page he says that "the lack of garbage collection makes C++ exceptions ... inherently defective." I'm not sure I agree with that. I think the opposite is more true. When you're using garbage collection, you can't rely on destructors to release resources (notably non-memory resources) when exceptions occur. In C# for example, the solution is supposed to be the 'using' statment, but that's only useful in the context of a function. It doesn't help you when you want class A to be a member of another class B and it's lifetime to be governed by the lifetime of class B.
Once upon a time, the 'scope' keyword was going to be extended to cover this case. It still might I suppose. The design of D 2.0 has been focused almost entirely on multiprogramming.
Sean
| |||
December 09, 2008 Re: Notes on Defective C++ | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | "Christopher Wright" <dhasenan@gmail.com> wrote in message news:ghkdnd$e95$1@digitalmars.com... > > And what are you going to throw an exception from, besides a function? I think you are talking about situations like this: > > class A > { > private File file; > this () { file = new File ("somePath"); } > // some operations with side effects that maybe close the file > } > > void foo () > { > auto a = new A; > // I want to make sure A's file is cleaned up...how? > } Yes. Thanks for the example. I do that sort of thing a lot, and it applies to anything with a handle such as mutexes, files, etc. In garbage-collected languages, what am I supposed to do there? It would seem that garbage collection and exceptions don't play nice together. Or am I missing something simple? Could a garbage-collected language ever figure out how to handle this? When class A goes out of scope, how would it know that the file object is not being referenced elsewhere? I wonder if there's a way that reference counting could be used in these cases. Jim | |||
December 09, 2008 Re: Notes on Defective C++ | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jim Hewes | Jim Hewes wrote:
> Yes. Thanks for the example. I do that sort of thing a lot, and it applies to anything with a handle such as mutexes, files, etc. In garbage-collected languages, what am I supposed to do there? It would seem that garbage collection and exceptions don't play nice together. Or am I missing something simple?
In this case, File should close itself in its destructor. Class A can't close its file in its destructor because the file might have already been collected and finalized. And you can't use a scope guard in this case because A doesn't let you just close the file.
I'd say that, if File doesn't close itself in its destructor, that's an error. If File has this error, A should offer a way to close the file without side effects.
| |||
December 14, 2008 Re: Notes on Defective C++ | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | "Christopher Wright" <dhasenan@gmail.com> wrote in message news:ghlntc$ku3$1@digitalmars.com... > In this case, File should close itself in its destructor. Class A can't close its file in its destructor because the file might have already been collected and finalized. And you can't use a scope guard in this case because A doesn't let you just close the file. > > I'd say that, if File doesn't close itself in its destructor, that's an error. If File has this error, A should offer a way to close the file without side effects. Well, File can clean up after itself in its own destructor, but the problem is you don't know when that will happen. This might be less of a problem with a file if you're not going to use that file again. But it might be more of a problem for things like mutexes that you want to be released right away. The solution in C# is that the class must provide a Dispose function. But then any owning class must remember to also provide a Dispose function and dispose of the disposable objects it owns. If you need to remember this, it becomes a source of possible error. It you've looked at the code (http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx) it's a bunch of extra stuff you need to do. It's kind of like going back to the C++ way of using new/delete for memory, having to remember to call delete, and not being allowed to use something like boost::shared_ptr. I agree that GC has taken us a step forward in dealing with memory resources, but it seems it was at the cost of not being able to deal with other resources as well. I'm not a compiler expert so I may be way off base. But I think what might be nice is if I can define a class as being reference counted instead of garbage collected. Then any time you create an instance of that class using "new", it would be assigned to a reference-counted reference, not garbage collected. The compiler would keep track of that automatically. The user of the reference counted class wouldn't have to know or remember to dispose it. I know reference counting can have performance penalties, but most of the time in my programs it doesn't matter. I'm not creating thousands of instances or references but only a few. Another problem cited with reference counting is circular references. But let me have the choice. I think I might at least alleviate that problem by using the equivalent to boost's weak pointers. Maybe it's better to think of memory and non-memory resources as different things and handle them differently as opposed to lumping them together using the same mechanism. I'm not sure if there is already a way to deal with this in D as I'm not quite that familiar with D. Jim | |||
December 14, 2008 Re: Notes on Defective C++ | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jim Hewes | Jim Hewes wrote:
> Maybe it's better to think of memory and non-memory resources as different things and handle them differently as opposed to lumping them together using the same mechanism. I'm not sure if there is already a way to deal with this in D as I'm not quite that familiar with D.
It requires that you design your classes differently. You were pretty much asking, if you don't change your design from something that worked in C++, will it work in D? And it won't, if you use D classes.
If you use D structs in D2, you get constructors and destructors for them, and you can use RAII like in C++. In D1 and D2, you can use scope classes (or scope instances).
In D, you could use the C# approach, though you don't have a using statement. You can instead use scope:
scope foo = new Disposable;
// do stuff
Or:
auto foo = new Disposable;
scope (exit) foo.dispose();
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply