D - RAII, take 3
- Walter (44/44) Sep 06 2002 This is an ongoing great discussion here, so I'm ready for a new strawma...
- Pavel Minayev (14/41) Sep 07 2002 I would prefer it to require "auto" (and stop with an error if it isn't
- Walter (3/10) Sep 08 2002 I think you're right.
- Sean L. Palmer (12/56) Sep 08 2002 I can see huge benefits of keeping auto instances as class members. I k...
- Walter (8/15) Sep 08 2002 know
- Sandor Hojtsy (22/66) Sep 09 2002 generate
- Walter (10/84) Sep 09 2002 I think Pavel's rationale for allowing auto classes to be passed as func...
- Patrick Down (2/2) Sep 09 2002 I like this proposal. I think it goes far enough
- Russell Lewis (16/16) Sep 09 2002 Perhaps we should be able to pass auto references (and references to
This is an ongoing great discussion here, so I'm ready for a new strawman proposal! First of all, while structs with destructors will work, they don't generate much enthusiasm. Making struct wrappers for class references is a lot of typing, and kludgy looking. It's hard to credibly explain why structs have destructors and not constructors. It just isn't good enough. Auto classes have problems - needing two versions, one with auto and one without. Auto storage class doesn't fit well with classes designed to be used solely with auto. So how about this: 1) Support an auto class characteristic, as in: auto class Foo { ... } 2) Support an auto storage class, as in: int foo() { auto Bar b; } An auto class: a) always gets auto storage class, whether or not it is explicitly listed as auto. b) sets a class to be auto and all classes derived from it c) cannot have its reference copied, passed as a function parameter, returned from a function, or the target of an inout or out parameter. d) cannot be a member of a struct or class, and cannot be statically allocated An auto storage class for an ordinary non-auto class: a) the reference can be copied, passed, assigned, and reassigned like a non-auto reference; it is up to the programmer to not mess it up In addition, for auto references, when they go out of scope, the ~this() function is called. However, a delete is not done. This means that the memory and the object remain instantiated. Hence, it is possible that the destructor may get run twice, so it should be written to do that safely: class File { FILE *fp; ~this() { if (fp) { fclose(fp); fp = NULL; } } } This should make most dangling references clean up harmlessly.
Sep 06 2002
Walter wrote:So how about this: 1) Support an auto class characteristic, as in: auto class Foo { ... } 2) Support an auto storage class, as in: int foo() { auto Bar b; }Great!An auto class: a) always gets auto storage class, whether or not it is explicitly listed as auto.I would prefer it to require "auto" (and stop with an error if it isn't there), but it isn't really important... I would be happy in any case =)c) cannot have its reference copied, passed as a function parameter, returned from a function, or the target of an inout or out parameter.This one I don't like. I understand the reasons, but it still sounds too limiting... a proposal: allow to pass it to functions, and store it in local variables, but not in static, globals and members. This should make sure that no dangling reference ever exists for an auto class object.d) cannot be a member of a struct or class, and cannot be statically allocatedEhm... okay.An auto storage class for an ordinary non-auto class: a) the reference can be copied, passed, assigned, and reassigned like a non-auto reference; it is up to the programmer to not mess it upYES!!!In addition, for auto references, when they go out of scope, the ~this() function is called. However, a delete is not done. This means that the memory and the object remain instantiated. Hence, it is possible that the destructor may get run twice, so it should be written to do that safely:Maybe let the compiler track this? Something like a hidden flag field in Object, checked before the destructor is run, and cleared afterwards? I think destructor running two times is just too weird for most C++ programmers, including me. It could be a source of many, many bugs!
Sep 07 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:ald4ql$1get$1 digitaldaemon.com...I think you're right.c) cannot have its reference copied, passed as a function parameter, returned from a function, or the target of an inout or out parameter.This one I don't like. I understand the reasons, but it still sounds too limiting... a proposal: allow to pass it to functions, and store it in local variables, but not in static, globals and members. This should make sure that no dangling reference ever exists for an auto class object.
Sep 08 2002
I can see huge benefits of keeping auto instances as class members. I know you want to keep D simple but without that capability you really have only halfway implemented RAII. When an auto instance goes out of scope, after calling the destructor, it can notify the GC that even though it still needs to manage the memory involved, it should not call the destructor. Just treat it as raw memory from then on. Sean "Walter" <walter digitalmars.com> wrote in message news:alb8e9$1o1u$1 digitaldaemon.com...This is an ongoing great discussion here, so I'm ready for a new strawman proposal! First of all, while structs with destructors will work, they don'tgeneratemuch enthusiasm. Making struct wrappers for class references is a lot of typing, and kludgy looking. It's hard to credibly explain why structs have destructors and not constructors. It just isn't good enough. Auto classes have problems - needing two versions, one with auto and one without. Auto storage class doesn't fit well with classes designed to be used solely with auto. So how about this: 1) Support an auto class characteristic, as in: auto class Foo { ... } 2) Support an auto storage class, as in: int foo() { auto Bar b; } An auto class: a) always gets auto storage class, whether or not it is explicitly listedasauto. b) sets a class to be auto and all classes derived from it c) cannot have its reference copied, passed as a function parameter, returned from a function, or the target of an inout or out parameter. d) cannot be a member of a struct or class, and cannot be statically allocated An auto storage class for an ordinary non-auto class: a) the reference can be copied, passed, assigned, and reassigned like a non-auto reference; it is up to the programmer to not mess it up In addition, for auto references, when they go out of scope, the ~this() function is called. However, a delete is not done. This means that the memory and the object remain instantiated. Hence, it is possible that the destructor may get run twice, so it should be written to do that safely: class File { FILE *fp; ~this() { if (fp) { fclose(fp); fp = NULL; } } } This should make most dangling references clean up harmlessly.
Sep 08 2002
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message news:algc3h$2jli$1 digitaldaemon.com...I can see huge benefits of keeping auto instances as class members. Iknowyou want to keep D simple but without that capability you really have only halfway implemented RAII.Perhaps, but I bet it is more like 95% <g>. But if it becomes obvious that this is a critical shortcoming, it can be added later without wrecking any existing code.When an auto instance goes out of scope, after calling the destructor, it can notify the GC that even though it still needs to manage the memory involved, it should not call the destructor. Just treat it as raw memory from then on.My intent with that is so that dangling references have a chance to fail gracefully rather than disastrously.
Sep 08 2002
"Walter" <walter digitalmars.com> wrote in message news:alb8e9$1o1u$1 digitaldaemon.com...This is an ongoing great discussion here, so I'm ready for a new strawman proposal! First of all, while structs with destructors will work, they don'tgeneratemuch enthusiasm. Making struct wrappers for class references is a lot of typing, and kludgy looking. It's hard to credibly explain why structs have destructors and not constructors. It just isn't good enough.Yes. Not for raii. But struct constructors and destructors are good on their own right.Auto classes have problems - needing two versions, one with auto and one without. Auto storage class doesn't fit well with classes designed to be used solely with auto. So how about this: 1) Support an auto class characteristic, as in: auto class Foo { ... } 2) Support an auto storage class, as in: int foo() { auto Bar b; } An auto class: a) always gets auto storage class, whether or not it is explicitly listedasauto. b) sets a class to be auto and all classes derived from it c) cannot have its reference copied, passed as a function parameter, returned from a function,What about calling member functions of an auto class, and messing with the "this"?or the target of an inout or out parameter. d) cannot be a member of a struct or class, and cannot be statically allocatedTheoretically yes. But too restrictive for any real case. Most uses of raii classes need non-destructing references to them. So this feature would be used in very few cases.An auto storage class for an ordinary non-auto class: a) the reference can be copied, passed, assigned, and reassigned like a non-auto reference; it is up to the programmer to not mess it upThe idea you suggested the first time. I would like to get some help from the compiler here. As I have already told: - Assignment to an auto reference should dispose the old object (compiler can build in this call) - Assignment from an auto to an other auto, should set the source auto reference to null. Both seems feasible.In addition, for auto references, when they go out of scope, the ~this() function is called. However, a delete is not done. This means that the memory and the object remain instantiated. Hence, it is possible that the destructor may get run twice, so it should be written to do that safely: class File { FILE *fp; ~this() { if (fp) { fclose(fp); fp = NULL; } } }Since it it not a real destructor (which absolutely cannot be called twice), I don't think we should call it ~this(). Why don't do this in the finalyze(), or create a new method: dispose() ?This should make most dangling references clean up harmlessly.
Sep 09 2002
I think Pavel's rationale for allowing auto classes to be passed as function parameters should resolve most of the issues here. -Walter "Sandor Hojtsy" <hojtsy index.hu> wrote in message news:alhl23$2mmq$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:alb8e9$1o1u$1 digitaldaemon.com...strawmanThis is an ongoing great discussion here, so I'm ready for a newhaveproposal! First of all, while structs with destructors will work, they don'tgeneratemuch enthusiasm. Making struct wrappers for class references is a lot of typing, and kludgy looking. It's hard to credibly explain why structstheirdestructors and not constructors. It just isn't good enough.Yes. Not for raii. But struct constructors and destructors are good onown right.listedAuto classes have problems - needing two versions, one with auto and one without. Auto storage class doesn't fit well with classes designed to be used solely with auto. So how about this: 1) Support an auto class characteristic, as in: auto class Foo { ... } 2) Support an auto storage class, as in: int foo() { auto Bar b; } An auto class: a) always gets auto storage class, whether or not it is explicitlyastheauto. b) sets a class to be auto and all classes derived from it c) cannot have its reference copied, passed as a function parameter, returned from a function,What about calling member functions of an auto class, and messing with the "this"?or the target of an inout or out parameter. d) cannot be a member of a struct or class, and cannot be statically allocatedTheoretically yes. But too restrictive for any real case. Most uses of raii classes need non-destructing references to them. So this feature would be used in very few cases.An auto storage class for an ordinary non-auto class: a) the reference can be copied, passed, assigned, and reassigned like a non-auto reference; it is up to the programmer to not mess it upThe idea you suggested the first time. I would like to get some help from the compiler here. As I have already told: - Assignment to an auto reference should dispose the old object (compiler can build in this call) - Assignment from an auto to an other auto, should set the source auto reference to null. Both seems feasible.In addition, for auto references, when they go out of scope, the ~this() function is called. However, a delete is not done. This means that the memory and the object remain instantiated. Hence, it is possible thattwice),destructor may get run twice, so it should be written to do that safely: class File { FILE *fp; ~this() { if (fp) { fclose(fp); fp = NULL; } } }Since it it not a real destructor (which absolutely cannot be calledI don't think we should call it ~this(). Why don't do this in the finalyze(), or create a new method: dispose() ?This should make most dangling references clean up harmlessly.
Sep 09 2002
I like this proposal. I think it goes far enough at this time.
Sep 09 2002
Perhaps we should be able to pass auto references (and references to auto classes) to functions, but only if the function reference is also 'auto': void func(auto MyClass foo) {...}; auto parameters are like auto references (can't be modified, can't be passed as a argument, except as an auto argument), except that it is NOT cleaned up when the function exits. The semantics mean more like "safe-for-auto" than really "auto". You could even return an auto reference (or have it as an out parameter) if the calling function was required to either 1) Save the return to an auto reference or 2) Immediately (and implicitly) finalize the object if it DOESN'T store the reference. I also vote with Pavel's mantra...'auto' classes should require the 'auto' keyword on their instance declarations, as well...
Sep 09 2002