Thread overview | |||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 25, 2002 RAII | ||||
---|---|---|---|---|
| ||||
Resource Aquisition Is Initialization (RAII) RAII is a programming paradigm where resources are automatically released when an object is no longer referenced. In C++, this is accomplished by putting the release code in a class destructor, and then the compiler will automatically insert the destructor call when the object goes out of scope. In D, automatic objects are structs, and structs do not have destructors. Classes have destructors (finalizers), but are only allocated on the gc heap, so the finalizer gets run at arbitrary and unpredictable times. D does support explicit finalization of objects: A a = new A(); ... delete a; but in the inevitable presence of exceptions, to make the code robust and reliable: try { A a = new A(); ... } finally { delete a; } While this does work, it can get tedious and unsightly when dealing with many such objects. The solution is to create a new storage class, raii: raii A a = new A(); All raii references will get a finally block created for them that calls delete on the reference. Of course, if the programmer stores a copy of a somewhere outside the scope, that reference will point to garbage once the scope is exited. |
August 25, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | On Sun, 25 Aug 2002 12:18:09 -0700 "Walter" <walter@digitalmars.com> wrote:
> The solution is to create a new storage class, raii:
>
> raii A a = new A();
>
> All raii references will get a finally block created for them that calls
> delete on the reference. Of course, if the programmer stores a copy of a
> somewhere
> outside the scope, that reference will point to garbage once the scope is
> exited.
Is it going to be part of D?
Just a suggestion... "raii" doesn't sound good =). I'd suggest using "auto"
instead.
|
August 25, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in news:akba6n$28tb$1@digitaldaemon.com: > > The solution is to create a new storage class, raii: > > raii A a = new A(); > > All raii references will get a finally block created for them that > calls delete on the reference. Of course, if the programmer stores a > copy of a somewhere > outside the scope, that reference will point to garbage once the scope > is exited. What happens if a is reassigned? Can A be reassigned? raii A a = new A(); a = new A(); I like "auto" better too. |
August 25, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | "Pavel Minayev" <evilone@omen.ru> wrote in message news:CFN374939933247569@news.digitalmars.com... > Is it going to be part of D? If no big problems with it show up. > Just a suggestion... "raii" doesn't sound good =). I'd suggest using "auto" > instead. Yeah, auto is probably better. |
August 25, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Patrick Down | "Patrick Down" <pat@codemoon.com> wrote in message news:Xns9275A0B6E350Cpatcodemooncom@63.105.9.61... > "Walter" <walter@digitalmars.com> wrote in > What happens if a is reassigned? Can A be reassigned? > > raii A a = new A(); > > a = new A(); In that case, the first a will get deleted by the gc when it gets around to it. Or you could explicitly do it via delete. |
August 25, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Excellent! auto is a better keyword though "Walter" <walter@digitalmars.com> wrote in message news:akba6n$28tb$1@digitaldaemon.com... > Resource Aquisition Is Initialization (RAII) > > RAII is a programming paradigm where resources are automatically released when an object is no longer referenced. In C++, this is accomplished by putting the release code in a class destructor, and then the compiler will automatically insert the destructor call when the object goes out of scope. > > In D, automatic objects are structs, and structs do not have destructors. > Classes have destructors (finalizers), but are only allocated on the gc > heap, > so the finalizer gets run at arbitrary and unpredictable times. D does > support explicit finalization of objects: > > A a = new A(); > ... > delete a; > > but in the inevitable presence of exceptions, to make the code robust and reliable: > > try > { > A a = new A(); > ... > } > finally > { > delete a; > } > > While this does work, it can get tedious and unsightly when dealing with many such objects. > > The solution is to create a new storage class, raii: > > raii A a = new A(); > > All raii references will get a finally block created for them that calls > delete on the reference. Of course, if the programmer stores a copy of a > somewhere > outside the scope, that reference will point to garbage once the scope is > exited. > > > |
August 26, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in message news:akba6n$28tb$1@digitaldaemon.com... > Resource Aquisition Is Initialization (RAII) > > RAII is a programming paradigm where resources are automatically released when an object is no longer referenced. In C++, this is accomplished by putting the release code in a class destructor, and then the compiler will automatically insert the destructor call when the object goes out of scope. > > In D, automatic objects are structs, and structs do not have destructors. > Classes have destructors (finalizers), but are only allocated on the gc > heap, > so the finalizer gets run at arbitrary and unpredictable times. D does > support explicit finalization of objects: > > A a = new A(); > ... > delete a; > > but in the inevitable presence of exceptions, to make the code robust and reliable: > > try > { > A a = new A(); > ... > } > finally > { > delete a; > } > > While this does work, it can get tedious and unsightly when dealing with many such objects. > > The solution is to create a new storage class, raii: > > raii A a = new A(); > > All raii references will get a finally block created for them that calls > delete on the reference. Of course, if the programmer stores a copy of a > somewhere > outside the scope, that reference will point to garbage once the scope is > exited. Hey, isn't that exactly the same that we was suggesting a few months ago? I thought it was ignored. And the same problem arises: In practice, RAII is not the property of the instance, but of the class, isn't it? Then you need to specify this at the class declaration of "A", so it cannot be a storage class. Thoughts? Yours, Sandor |
August 26, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sandor Hojtsy | In article <akd1sb$1ed6$1@digitaldaemon.com>, Sandor Hojtsy says... >"Walter" <walter@digitalmars.com> wrote in message news:akba6n$28tb$1@digitaldaemon.com... >> Resource Aquisition Is Initialization (RAII) >> >> RAII is a programming paradigm where resources are automatically released when an object is no longer referenced. In C++, this is accomplished by [clip] > >Hey, isn't that exactly the same that we was suggesting a few months ago? >I thought it was ignored. >And the same problem arises: >In practice, RAII is not the property of the instance, but of the class, >isn't it? >Then you need to specify this at the class declaration of "A", so it cannot >be a storage class. >Thoughts? > >Yours, >Sandor I don't know about the "suggesting a few months ago", since I am a very sporadic participant in this newsgroup (highly active for short periods, then nothing for quite awhile...). I do, however, agree that scoping is almost always going to be a property of the class, not the instances. Arguably, making it an instance is more flexible (if you have some reason to make a non-auto instance, you can), but you can now hose your program by forgetting to put the 'auto' in front of one of your instances. This could be fatal for something like a mutex -- if other threads got locked up before the GC ran, you could end up deadlocking the entire program over a mutex that should have been freed. Yes, it is a bug to forget the 'auto', but it would likewise be a bug to forget the 'try{}finally{}' that is being replaced by the auto. If it is doable, I would prefer that 'auto' be a class property ( auto class Lock{} ). If flexibility is a problem, and it becomes necessary for a particular instance of an 'auto class' to outlive its scope (unlikely, but it is possible), and if un-autoing the class is simply not an acceptable solution, perhaps a keyword like 'collected' or 'non_auto' could be added (it doesn't have to look nice -- it will be used VERY infrequently and should only be used by people who really know what they are doing) as a storage class so that it disabled 'auto'ness for a particular instance. Or, to flog a fatally wounded horse one last time, you could implement reference counting and get the RAII that you originally described : "RAII is a programming paradigm where resources are automatically released when an object is no longer referenced." C++'s method is a limited subset of what RAII really should be. If you can automatically implement the pseudo-finally to perform a delete for auto instances, you can automatically implement a pseudo-finally to decrement the reference count for a counted instance. The only reason for un-autoing an instance of an auto class (that I can think of) is to pass the instance on to someone else (it is occasionally necessary to transfer ownership of a synchronization lock). Reference counting handles this case without needing another keyword or any other special handling. The act of handing off the instance increases the refcount, keeping the instance alive. Reference counting also solves the: { auto A a = new A; // A1 a = new A; // A2 } where A2 gets deleted but A1 waits for the GC to get around to it (which is not RAII or deterministic). Refcounting would have to watch assignments, and modify the refcount for the old object as well as the new. But when it did that, it would notice that A1 was no longer used and could finalize it (I defer to the masses on whether it should be deleted or not, but it definitely should be finalized). As for whether the suggested 'counted' should be an instance or class property, I suspect the argument given above for class property still holds. Classes should be counted, not instances. Part of the reason for this is that a refcounted instance could be returned from a function and still be valid. If refcounting is an instance property, the external storage instance (the variable that stores the function return value) would also have to be refcounted to maintain the refcounting invariant. If the property belongs to the class, then all instances of the class are refcounted, and life is good. Also, by making it a class property, you can set a flag in the symbol table that says that this class: 1. is synchronized (refcounting must be thread safe) 2. contains a refcount field 3. has additional refcounting prolog or epilog in its assignment operator 4. <anything else that comes up as being necessary for refcounting> That way you don't have to track it on a per-instance basis, which should simplify processing. Because derived types can be assigned into base type references, it may be necessary to consider the interaction of inheritance and the 'counted' class specifier. Are all children of a counted class automatically counted? Can instances of counted classes be polymorphically assigned into non-counted base references? How about the other way around? It may also become necessary to make assignments across refcounting boundaries illegal, at least for current compilers, until the potential needs/problems are understood better. I realize that actually stopping *only* assignments across the refcounting border would require a runtime check. Perhaps a compile time restraint that simply says that counted classes are not allowed to participate in polymorphic assignments at all would be a better first solution... Yes, there are complications with 'counted' classes. But realistically, either compiler writers or programmers are going to experience similar complications with 'auto' classes (and worse problems with 'auto' instances). If the problems are roughly the same, I would vote for the more flexible and complete solution. Of course, I am somewhat biased on the issue... As a quick comment, if 'auto' is going to win out over 'counted', I would prefer 'scoped' over 'auto', because 'auto' means so many different things. 'scoped' (at least to me) is very explicit about exactly what behavior you are modifying. Of course, if you are worried about adding common keywords, 'scoped' is not currently a keyword in other languages, but I think 'auto' is already reserved in C/C++, which would make it a better choice from that standpoint. Mac |
August 26, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mac Reiter | "Mac Reiter" <Mac_member@pathlink.com> wrote in message news:akdgqc$218p$1@digitaldaemon.com... > In article <akd1sb$1ed6$1@digitaldaemon.com>, Sandor Hojtsy says... > >Hey, isn't that exactly the same that we was suggesting a few months ago? I thought it was ignored. I think it was suggested, though I can't recall who did. It might have been Pavel. > >And the same problem arises: > >In practice, RAII is not the property of the instance, but of the class, > >isn't it? > >Then you need to specify this at the class declaration of "A", so it cannot > >be a storage class. > >Thoughts? Making it a property of the class, rather than the instance, leads to much implementation grief. For example, pulling on that thread a bit <g>, it seems to lead to needing to implement two versions of each class - one counted, one not. > If it is doable, I would prefer that 'auto' be a class property ( auto class > Lock{} ). If flexibility is a problem, and it becomes necessary for a particular instance of an 'auto class' to outlive its scope (unlikely, but it is > possible), and if un-autoing the class is simply not an acceptable solution, > perhaps a keyword like 'collected' or 'non_auto' could be added (it doesn't have > to look nice -- it will be used VERY infrequently and should only be used by > people who really know what they are doing) as a storage class so that it disabled 'auto'ness for a particular instance. While in C++ it is common to have a destructor (to manage memory), in D having a resource that needs cleaning up should be the exception, not the rule. > Or, to flog a fatally wounded horse one last time, you could implement reference > counting and get the RAII that you originally described : "RAII is a programming > paradigm where resources are automatically released when an object is no longer > referenced." C++'s method is a limited subset of what RAII really should be. > If you can automatically implement the pseudo-finally to perform a delete for > auto instances, you can automatically implement a pseudo-finally to decrement > the reference count for a counted instance. The only reason for un-autoing an > instance of an auto class (that I can think of) is to pass the instance on to > someone else (it is occasionally necessary to transfer ownership of a synchronization lock). Reference counting handles this case without needing > another keyword or any other special handling. The act of handing off the instance increases the refcount, keeping the instance alive. Reference counting involves far, far more than just a pseudo-finally. > Reference counting also solves the: > > { > auto A a = new A; // A1 > a = new A; // A2 > } > > where A2 gets deleted but A1 waits for the GC to get around to it (which is not > RAII or deterministic). Refcounting would have to watch assignments, and modify > the refcount for the old object as well as the new. But when it did that, it > would notice that A1 was no longer used and could finalize it (I defer to the > masses on whether it should be deleted or not, but it definitely should be finalized). At least in D the resource would eventually get cleaned up on the GC pass, whereas in C++ it is a memory leak that will never get cleaned up. > As for whether the suggested 'counted' should be an instance or class property, > I suspect the argument given above for class property still holds. Classes > should be counted, not instances. Part of the reason for this is that a refcounted instance could be returned from a function and still be valid. If > refcounting is an instance property, the external storage instance (the variable > that stores the function return value) would also have to be refcounted to maintain the refcounting invariant. If the property belongs to the class, then > all instances of the class are refcounted, and life is good. Also, by making it > a class property, you can set a flag in the symbol table that says that this > class: > 1. is synchronized (refcounting must be thread safe) > 2. contains a refcount field > 3. has additional refcounting prolog or epilog in its assignment operator > 4. <anything else that comes up as being necessary for refcounting> > That way you don't have to track it on a per-instance basis, which should > simplify processing. > > Because derived types can be assigned into base type references, it may be necessary to consider the interaction of inheritance and the 'counted' class > specifier. Are all children of a counted class automatically counted? Can > instances of counted classes be polymorphically assigned into non-counted base > references? How about the other way around? It may also become necessary to > make assignments across refcounting boundaries illegal, at least for current > compilers, until the potential needs/problems are understood better. I realize > that actually stopping *only* assignments across the refcounting border would > require a runtime check. Perhaps a compile time restraint that simply says that > counted classes are not allowed to participate in polymorphic assignments at all > would be a better first solution... Suppose you have a printing function that takes an object of type Object. Object is not counted, so the counted class is cast to Object. To support this, it becomes necessary to 1) extend counting to every object 2) ignore the possibility of bugs from dangling references 3) disallow conversions to Object. 1) has too many penalties for D as whole 2) is a similar bug to handing off a reference to an 'auto' instance, but I think worse because it will happen more often 3) requires creation of two versions of most things in the library, one to handle counted and one for non-counted > Yes, there are complications with 'counted' classes. But realistically, either > compiler writers or programmers are going to experience similar complications > with 'auto' classes (and worse problems with 'auto' instances). If the problems > are roughly the same, I would vote for the more flexible and complete solution. > Of course, I am somewhat biased on the issue... No, I believe the 'auto' approach has an order of magnitude less implementation effort than ref counting. For example, it won't be necessary to handle arrays of counted objects, counted objects as members of structs, counted objects as members of non-counted objects, assignment overloading, etc. > As a quick comment, if 'auto' is going to win out over 'counted', I would prefer > 'scoped' over 'auto', because 'auto' means so many different things. 'scoped' > (at least to me) is very explicit about exactly what behavior you are modifying. > Of course, if you are worried about adding common keywords, 'scoped' is not > currently a keyword in other languages, but I think 'auto' is already reserved > in C/C++, which would make it a better choice from that standpoint. auto does have the nice advantage that people recognize it as a keyword. |
August 26, 2002 Re: RAII | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pavel Minayev | Pavel Minayev wrote:
> On Sun, 25 Aug 2002 12:18:09 -0700 "Walter" <walter@digitalmars.com> wrote:
>
>
>>The solution is to create a new storage class, raii:
>>
>> raii A a = new A();
>>
>>All raii references will get a finally block created for them that calls
>>delete on the reference. Of course, if the programmer stores a copy of a
>>somewhere
>>outside the scope, that reference will point to garbage once the scope is
>>exited.
>
> Is it going to be part of D?
> Just a suggestion... "raii" doesn't sound good =). I'd suggest using "auto" instead.
I get nightmares of "riaa" objects...
|
Copyright © 1999-2021 by the D Language Foundation