D - Force-delete objects?
- Russ Lewis (35/35) Mar 13 2002 I think that it would be useful to be able to have a "force-delete"
- Russ Lewis (18/23) Mar 13 2002 A note:
- Walter (9/21) Mar 13 2002 could
- Immanuel Scholz (28/58) Mar 13 2002 I thought calling delete on an object immediatly destroy it and does not
- Russ Lewis (14/32) Mar 13 2002 No, your understanding is correct. (Or, at least, it matches my
- Pavel Minayev (4/6) Mar 13 2002 It does. What Russ wants is an object that's deleted _automatically_
- Walter (13/19) Mar 16 2002 What this does is add back in C++ semantics for auto-destruction of obje...
- Sean L. Palmer (22/41) Mar 16 2002 Destructor semantics are very handy. Let's say I have a 3D Model object
- Walter (6/21) Mar 16 2002 and
- Sean L. Palmer (16/40) Mar 17 2002 Does that not sound like a gigantic kludge to you? I don't want to be
- Walter (14/26) Mar 19 2002 in
- Pavel Minayev (14/21) Mar 17 2002 objects.
- Walter (7/28) Mar 17 2002 the
- Pavel Minayev (9/12) Mar 17 2002 but
- Russ Lewis (10/13) Mar 18 2002 Can't we just say that for these types of objects the compiler implicitl...
- Russell Borogove (10/23) Mar 18 2002 I'll just throw in my $0.02 here -- one of the few
- Walter (10/18) Mar 23 2002 objects
- Pavel Minayev (41/45) Mar 24 2002 There won't be any temproraries there, since we work with references
- Patrick Down (12/29) Mar 24 2002 What about this...
- Pavel Minayev (7/17) Mar 24 2002 The object created first is collected by the GC, since there are no
- Patrick Down (103/138) Mar 17 2002 ends.
-
Roberto Mariottini
(16/54)
Mar 18 2002
"Patrick Down"
ha scritto nel messaggio - Patrick Down (40/68) Mar 18 2002 =====================================================
- Russ Lewis (13/16) Mar 18 2002 Force-delete doesn't impact the complexity of cleanup code. In any
- Sean L. Palmer (13/43) Mar 13 2002 I like this idea, but don't think you'd have to specify the storage clas...
- Russ Lewis (11/21) Mar 13 2002 In general, this would work for most applications, but I also have code ...
- Jim Starkey (18/27) Mar 22 2002 I think it's time to unravel the need for a feature and way it was
- DrWhat? (34/34) Mar 25 2002 I suppose the question is "when should an object be deleted?"
I think that it would be useful to be able to have a "force-delete" storage class (or some such) for CLASS REFERENCES that would automatically delete the class object when the reference went out of scope. That is, basically, it would be a class object that was NOT garbage collected. This would be useful for things that need to be cleaned up quickly. People have suggested that open files should be cleaned up (to close the file); I run across things in multithreaded programming that are similar. In C++, I do things like this: class Lock; class Locker { private: Lock *lockThis; public: Locker(Lock *lockThis) { this->lockThis = lockThis; lockThis->Lock(); }; ~Locker() { lockThis->Unlock(); }; }; which allows me to write code like this: { Locker lock(collectionObject->lock) ... // do stuff with collection Object } // collectionObject is automatically unlocked when we go out of scope, // either by returning, continuing out of the block, or throwing an exception Obviously, in my style of code, delayed GC is NOT acceptable. You could force the programmer to call delete; as he leaves the block...but the whole point of this object was to make it so the programmer DIDN'T have to remember to unlock everything - it's a failsafe. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 13 2002
Russ Lewis wrote:I think that it would be useful to be able to have a "force-delete" storage class (or some such) for CLASS REFERENCES that would automatically delete the class object when the reference went out of scope. That is, basically, it would be a class object that was NOT garbage collected.A note: This is where I (again) am really in favor of a reference counting GC. If you had reference counting, then you could make a syntax rule that you could not mix "force-delete" and normal references in assignments. Then, you could still have the object persist beyond the scope of the block, but it would IMMEDIATELY be deleted when the last reference went away. Yes, yes, I know loops are a problem. But David Bacon (of IBM Research) has a system that can auto-detect loops in a reference-counting system. If you use a non-concurrent collector (i.e. you stop all threads in the program while the collector runs), then the algorithm to detect loops is actually remarkably trivial. He has also posted another, more complex, test that will work with concurrent collectors. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 13 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C8F883A.3C5903F0 deming-os.org...A note: This is where I (again) am really in favor of a reference counting GC. If you had reference counting, then you could make a syntax rule that youcouldnot mix "force-delete" and normal references in assignments. Then, you could still have the object persist beyond the scope of the block, but it would IMMEDIATELY be deleted when the last reference went away. Yes, yes, I know loops are a problem. But David Bacon (of IBM Research)hasa system that can auto-detect loops in a reference-counting system. Ifyouuse a non-concurrent collector (i.e. you stop all threads in the program while the collector runs), then the algorithm to detect loops is actually remarkably trivial. He has also posted another, more complex, test that will work with concurrent collectors.Reference counting would be a big problem to implement in D due to D's support of interior pointers possibly being the only references to an object. Interior pointers are necessary to support array slicing and interfacing easilly to C.
Mar 13 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> schrieb im Newsbeitrag news:3C8F869F.F8A5B82A deming-os.org...I think that it would be useful to be able to have a "force-delete" storage class (or some such) for CLASS REFERENCES that would automatically delete the class object when the reference went out of scope. That is, basically, it would be a class object that was NOT garbage collected.I thought calling delete on an object immediatly destroy it and does not wait until gc catch up? If this is not so, I think it should be made like this, or are there reasons to not make delete act like this?This would be useful for things that need to be cleaned up quickly. People have suggested that open files should be cleaned up (to close the file); I run across things in multithreaded programming that are similar. In C++, I do things like this:as you mention the word "multithreaded", I remember a issue, where reference counting can heavily impact the performance on multithreaded enviroment. Are there the possibility to forbid reference counting on objectst? Maybe with a keyword?class Lock; class Locker { private: Lock *lockThis; public: Locker(Lock *lockThis) { this->lockThis = lockThis; lockThis->Lock(); }; ~Locker() { lockThis->Unlock(); }; }; which allows me to write code like this: { Locker lock(collectionObject->lock) ... // do stuff with collection Object } // collectionObject is automatically unlocked when we go out of scope, // either by returning, continuing out of the block, or throwing an exceptionI think "RAII" (resource allocation is initialisation) in D is written like this: { lock_something(); // allocation ... } finally { unlock(); // deallocation } I dislike this in some kind too, because it lacks some of the coolines of the c++ - way (as example, the destructor is never called, when an exception within the constructor is thrown), but I think I may get used to it...Obviously, in my style of code, delayed GC is NOT acceptable. You could force the programmer to call delete; as he leaves the block...but the whole point of this object was to make it so the programmer DIDN'T have to remember to unlock everything - it's a failsafe.You may directly call to the destructor in finally {}... But since you may call to unlock as well, there is no more use for a sentry-class like Locker Imi
Mar 13 2002
Immanuel Scholz wrote:I thought calling delete on an object immediatly destroy it and does not wait until gc catch up? If this is not so, I think it should be made like this, or are there reasons to not make delete act like this?No, your understanding is correct. (Or, at least, it matches my understanding.) But if I force programmers to code a delete, then there's no need for my Locker class.as you mention the word "multithreaded", I remember a issue, where reference counting can heavily impact the performance on multithreaded enviroment. Are there the possibility to forbid reference counting on objectst? Maybe with a keyword?Currently, D's GC is NOT a reference counter (see my other post on the subject).I think "RAII" (resource allocation is initialisation) in D is written like this: { lock_something(); // allocation ... } finally { unlock(); // deallocation }Right. D can do this far more cleanly than C++ (we can consolidate all of the cleanup into the finally block), but it still forces programmers to remember it. I have had way too many forgotten locks in my own code to trust my own memory :) -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 13 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a6o69m$1vif$1 digitaldaemon.com...I thought calling delete on an object immediatly destroy it and does not wait until gc catch up?It does. What Russ wants is an object that's deleted _automatically_ when its scope ends.
Mar 13 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a6o7s4$206h$1 digitaldaemon.com..."Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a6o69m$1vif$1 digitaldaemon.com...What this does is add back in C++ semantics for auto-destruction of objects. Unfortunately, that drags along a great deal of complexity internal to the compiler, coupled with all kinds of obscure rules about when temporaries are destructed, interactions with various features like ?:, and lots of inevitable obscure implementation bugs. Adding this in will mean that D will no longer be a small, easy to understand and implement language. Far and away most uses of resource deallocation are memory releases, which is not necessary with garbage collection. The next most common use is releasing mutex locks, which is handled by the "synchronize" features of D. What's left should not be too onerous to use with explicit finally blocks.I thought calling delete on an object immediatly destroy it and does not wait until gc catch up?It does. What Russ wants is an object that's deleted _automatically_ when its scope ends.
Mar 16 2002
Destructor semantics are very handy. Let's say I have a 3D Model object class Model3D { private: IDirect3DVertexBuffer8* vb; IDirect3DTexture8* tex; public: this() { /+ load model here +/ } ~this() { vb->Release(); tex->Release(); } }; If your language gives you no guarantees that the destructor will ever get called, you cannot make sure that your program leaves something in a consistent state. You can't use try...finally in the above situation. This kind of thing is more common than you think. It's not just mutex's and memory we have to manage. Sean "Walter" <walter digitalmars.com> wrote in message news:a707f0$1qif$1 digitaldaemon.com..."Pavel Minayev" <evilone omen.ru> wrote in message news:a6o7s4$206h$1 digitaldaemon.com...not"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a6o69m$1vif$1 digitaldaemon.com...I thought calling delete on an object immediatly destroy it and doesobjects.What this does is add back in C++ semantics for auto-destruction ofwait until gc catch up?It does. What Russ wants is an object that's deleted _automatically_ when its scope ends.Unfortunately, that drags along a great deal of complexity internal to the compiler, coupled with all kinds of obscure rules about when temporariesaredestructed, interactions with various features like ?:, and lots of inevitable obscure implementation bugs. Adding this in will mean that D will no longer be a small, easy to understand and implement language. Far and away most uses of resource deallocation are memory releases, which is not necessary with garbage collection. The next most common use is releasing mutex locks, which is handled by the "synchronize" features ofD.What's left should not be too onerous to use with explicit finally blocks.
Mar 16 2002
"Sean L. Palmer" <spalmer iname.com> wrote in message news:a70eoj$1ujd$1 digitaldaemon.com...Destructor semantics are very handy. Let's say I have a 3D Model object class Model3D { private: IDirect3DVertexBuffer8* vb; IDirect3DTexture8* tex; public: this() { /+ load model here +/ } ~this() { vb->Release(); tex->Release(); } }; If your language gives you no guarantees that the destructor will ever get called, you cannot make sure that your program leaves something in a consistent state. You can't use try...finally in the above situation. This kind of thing is more common than you think. It's not just mutex'sandmemory we have to manage.I understand the problem. What you can do is construct a list of such critical objects, and run the release on them in a finally block off of the program entry point.
Mar 16 2002
Does that not sound like a gigantic kludge to you? I don't want to be polluting my main() function with stuff that conceptually should be done in a finalize method of an object. Sure we can use delete obj; and manually call the GC when we need to... I would just like some guarantees from the language that the destructor will get called for every object that is collected, and that every object will be collected as the program shuts down. If the compiler could automatically "collect" objects that simply go out of scope when it knows that no pointers to the object have been stored anywhere (the code never takes the address of the object for instance, or never stores it or sends it anywhere), that would be real nice too. Sean "Walter" <walter digitalmars.com> wrote in message news:a71609$2dcd$1 digitaldaemon.com..."Sean L. Palmer" <spalmer iname.com> wrote in message news:a70eoj$1ujd$1 digitaldaemon.com...getDestructor semantics are very handy. Let's say I have a 3D Model object class Model3D { private: IDirect3DVertexBuffer8* vb; IDirect3DTexture8* tex; public: this() { /+ load model here +/ } ~this() { vb->Release(); tex->Release(); } }; If your language gives you no guarantees that the destructor will everthecalled, you cannot make sure that your program leaves something in a consistent state. You can't use try...finally in the above situation. This kind of thing is more common than you think. It's not just mutex'sandmemory we have to manage.I understand the problem. What you can do is construct a list of such critical objects, and run the release on them in a finally block off ofprogram entry point.
Mar 17 2002
"Sean L. Palmer" <spalmer iname.com> wrote in message news:a732ft$gum$1 digitaldaemon.com...Does that not sound like a gigantic kludge to you? I don't want to be polluting my main() function with stuff that conceptually should be doneina finalize method of an object.It doesn't have to be main(), just places in your program that suggest themselves as a convenient place to put them.Sure we can use delete obj; and manually call the GC when we need to... I would just like some guarantees from the language that the destructor will get called for every object that is collected, and that every object willbecollected as the program shuts down.main() does automatically run a collection cycle upon completion. However, it is still possible that there's a dangling reference in the stack and static data. It's possible the gc could be changed to ignore them for the final collection.If the compiler could automatically "collect" objects that simply go out of scope when it knows that nopointersto the object have been stored anywhere (the code never takes the addressofthe object for instance, or never stores it or sends it anywhere), that would be real nice too.The problem is it isn't simple. There's a lot of implementation required to get it right.
Mar 19 2002
"Walter" <walter digitalmars.com> wrote in message news:a707f0$1qif$1 digitaldaemon.com...What this does is add back in C++ semantics for auto-destruction ofobjects.Unfortunately, that drags along a great deal of complexity internal to the compiler, coupled with all kinds of obscure rules about when temporariesaredestructed, interactions with various features like ?:, and lots of inevitable obscure implementation bugs. Adding this in will mean that D will no longer be a small, easy to understand and implement language.No, no, that wasn't the point. The idea was to add some kind of attribute ("auto"?) for locals that forces them to be deleted immediately when their scope ends. It has nothing to do with temporaries or C++-style stack objects: void foo() { auto File file = new File; ... // file is automatically deleted at the end of function }
Mar 17 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a71isi$2kvd$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:a707f0$1qif$1 digitaldaemon.com...theWhat this does is add back in C++ semantics for auto-destruction ofobjects.Unfortunately, that drags along a great deal of complexity internal toends.compiler, coupled with all kinds of obscure rules about when temporariesaredestructed, interactions with various features like ?:, and lots of inevitable obscure implementation bugs. Adding this in will mean that D will no longer be a small, easy to understand and implement language.No, no, that wasn't the point. The idea was to add some kind of attribute ("auto"?) for locals that forces them to be deleted immediately when their scopeIt has nothing to do with temporaries or C++-style stack objects: void foo() { auto File file = new File; ... // file is automatically deleted at the end of function }I think it is analogous to the way C++ calls destructors on stack objects when they go out of scope. The problem isn't that they are on the stack, but the complicated rules for doing the destructors.
Mar 17 2002
"Walter" <walter digitalmars.com> wrote in message news:a72klf$6ft$1 digitaldaemon.com...I think it is analogous to the way C++ calls destructors on stack objects when they go out of scope. The problem isn't that they are on the stack,butthe complicated rules for doing the destructors.What's wrong with the rules? Just destruct the objects in reversed order: File a, b; ... // b destroyed // a destroyed I don't see any complexity here... where am I wrong?
Mar 17 2002
Walter wrote:I think it is analogous to the way C++ calls destructors on stack objects when they go out of scope. The problem isn't that they are on the stack, but the complicated rules for doing the destructors.Can't we just say that for these types of objects the compiler implicitly generates a finally {} block which deletes them? It does add some complexity, but not much. Compilers that don't support that feature (yet) just throw compile-time errors on the type modifier :) -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 18 2002
Russ Lewis wrote:Walter wrote:I'll just throw in my $0.02 here -- one of the few places where C++ really becomes elegant is when you want to put a resource-grabbing object, or a debugging object as an auto variable in a function, and have it naturally cleaned up on function exit. Reviving C's vestigial "auto" declaration to say "please destroy at the end of this function/block" seems like a reasonable way to do this. -RBI think it is analogous to the way C++ calls destructors on stack objects when they go out of scope. The problem isn't that they are on the stack, but the complicated rules for doing the destructors.Can't we just say that for these types of objects the compiler implicitly generates a finally {} block which deletes them? It does add some complexity, but not much. Compilers that don't support that feature (yet) just throw compile-time errors on the type modifier :)
Mar 18 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C963321.EFBC360F deming-os.org...Walter wrote:objectsI think it is analogous to the way C++ calls destructors on stackbutwhen they go out of scope. The problem isn't that they are on the stack,complexity,the complicated rules for doing the destructors.Can't we just say that for these types of objects the compiler implicitly generates a finally {} block which deletes them? It does add somebut not much. Compilers that don't support that feature (yet) just throw compile-time errors on the type modifier :)That's just what C++ does. Things get complicated, though, for destruction of temporaries that may or may not have been created, for ?: expressions that might have been short circuited, construction objects as function parameters, and then an exception happens before the function gets called, etc.
Mar 23 2002
"Walter" <walter digitalmars.com> wrote in message news:a7k4io$mbt$1 digitaldaemon.com...Things get complicated, though, for destruction of temporaries that may or may not have been created, for ?: expressions that might have been short circuited, construction objects as function parameters, and then an exception happens before the function gets called, etc.There won't be any temproraries there, since we work with references rather than objects. This is an important difference from C++ - here, the only thing the compiler should do is to guarantee that any auto reference gets deleted at the end of the scope. In fact, it just means implicitly inserting delete statements at the end of the block, after every break, and in final section of each try block. Another tricky thing is that the block must be wrapped an invisible try..finally block: void foo() { while (true) { /* try { */ auto File file = new File; ... if (file.eof()) { /* delete file; */ break; } ... file.read(n); // could raise an exception ... try file.write(n); finally { n = 0; /* delete file; */ } ... /* } finally { delete file; } */ } } Of course, there's also goto, but in this case you could just state that "goto doesn't delete auto references" - so if somebody is smart enough to goto out of block (instead of, say, break'ing), he should take care of deleting all autos himself. Are these rules complex? I wouldn't say so...
Mar 24 2002
"Pavel Minayev" <evilone omen.ru> wrote in news:a7keme$1aig$1 digitaldaemon.com:"Walter" <walter digitalmars.com> wrote in message news:a7k4io$mbt$1 digitaldaemon.com...What about this... void bar(out Obj a) { a = new Obj; } void foo() { auto Obj b = new Obj; bar(b); }Things get complicated, though, for destruction of temporaries that may or may not have been created, for ?: expressions that might have been short circuited, construction objects as function parameters, and then an exception happens before the function gets called, etc.There won't be any temproraries there, since we work with references rather than objects. This is an important difference from C++ - here, the only thing the compiler should do is to guarantee that any auto reference gets deleted at the end of the scope. In fact, it just means implicitly inserting delete statements at the end of the block, after every break, and in final section of each try block. Another tricky thing is that the block must be wrapped an invisible try..finally block:
Mar 24 2002
"Patrick Down" <pat codemoon.com> wrote in message news:Xns91DB6CC9E77BApatcodemooncom 63.105.9.61...What about this... void bar(out Obj a) { a = new Obj; } void foo() { auto Obj b = new Obj; bar(b); }The object created first is collected by the GC, since there are no references left to it. The second one (constructed in bar()) gets deleted at the end of function. This leads to a decision that all auto objects shouldn't be changed once assigned, as if it was declared const in C++.
Mar 24 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a71isi$2kvd$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:a707f0$1qif$1 digitaldaemon.com...ends.Adding this in will mean that D will no longer be a small, easy to understand and implement language.No, no, that wasn't the point. The idea was to add some kind of attribute ("auto"?) for locals that forces them to be deleted immediately when their scopeIt has nothing to do with temporaries or C++-style stack objects: void foo() { auto File file = new File; ... // file is automatically deleted at the end of function }I think the problem that Walter has with this is that determining when an object's scope ends is a hard. Just consider looping or try statement scopes with break, continue, return, or goto statements. But I wonder since we are only talking about heap based objects if there is not a easier way to handle this. Consider the following code. int foo() { int doneOnce = 0; lable1: auto File file = new File; for(int i=0; i < 10; ++i) { auto SomeObj a = new SomeObj; if(a.SomeFunc()) continue; auto SomeObj b = new SomeObj; if(b.SomeFunc()) return 1; } if(doneOnce) { doneOnce = 1; goto lable1; } return 2; } Could this be made to work with some very simple rules? 1. Determine all your auto varaibles an initialize them to null at the beginning of the function. 2. Make a cleanup section that deletes all the autos at the end of the function. 3. Every assignment to an auto variable is preceeded by a delete of that object. So the compiler would translate translate the above function into something like this? Assume delete does a null test. int foo() { int rtn; File file = null; SomeObj a = null; SomeObj b = null; int doneOnce = 0; lable1: delete file; file = new File; for(int i=0; i < 10; ++i) { delete a; a = new SomeObj; if(a.SomeFunc()) continue; delete b; b = new SomeObj; if(b.SomeFunc()) { rtn = 1; goto cleanup; } } if(doneOnce) { doneOnce = 1; goto lable1; } rtn = 2; cleanup: delete file; delete a; delete b; return rtn; } Now function calls and return statements need a little consideration. out paramneters are like assignments so rule 3 applies. Since you really can't tell with an inout don't allow it. Don't allow auto variables to be returned for obvious reasons. void FuncIn(in SomeObj a) { } void FuncOut(out SomeObj a) { } void FuncInOut(inout SomeObj a) { } SomeObj foo() { auto SomeObj a = new SomeObj; // This is ok just hope FuncIn doesn't do somthing // silly like store the object or delete it FuncIn(a); // This is ok FuncOut(a); // but a must be deleted before the function call // This is an error can't use auto variables as inout // parameters FuncInOut(a); // This is an error can't return auto variables return a; }Unfortunately, that drags along a great deal of complexity internal to the compiler, coupled with all kinds of obscure rules about when temporariesaredestructed, interactions with various features like ?:, and lots of inevitable obscure implementation bugs. Adding this in will mean that D will no longer be a small, easy to understand and implement language.No, no, that wasn't the point. The idea was to add some kind of attribute ("auto"?) for locals that forces them to be deleted immediately when their scope ends. It has nothing to do with temporaries or C++-style stack objects: void foo() { auto File file = new File; ... // file is automatically deleted at the end of function }
Mar 17 2002
"Patrick Down" <pdown austin.rr.com> ha scritto nel messaggio news:a72u86$dkt$1 digitaldaemon.com... [...]Could this be made to work with some very simple rules? 1. Determine all your auto varaibles an initialize them to null at the beginning of the function. 2. Make a cleanup section that deletes all the autos at the end of the function. 3. Every assignment to an auto variable is preceeded by a delete of that object.It seems to me a good starting point. But how will you deal with exceptions?So the compiler would translate translate the above function into something like this? Assume delete does a null test.[... snip code example ...]Now function calls and return statements need a little consideration. out paramneters are like assignments so rule 3 applies. Since you really can't tell with an inout don't allow it. Don't allow auto variables to be returned for obvious reasons. void FuncIn(in SomeObj a) { } void FuncOut(out SomeObj a) { } void FuncInOut(inout SomeObj a) { } SomeObj foo() { auto SomeObj a = new SomeObj; // This is ok just hope FuncIn doesn't do somthing // silly like store the object or delete it FuncIn(a);I can live with this security limitation.// This is ok FuncOut(a); // but a must be deleted before the function call // This is an error can't use auto variables as inout // parameters FuncInOut(a);Why?// This is an error can't return auto variables return a; }And what if one of theese functions do a "delete" on the auto object? And what about assignments? I mean { auto Object1 a; Object1 b; b = a; Func(b); // storing the pointer? } // now going out of scope... Ciao
Mar 18 2002
===================================================== "Roberto Mariottini" <rmariottini lycosmail.com> wrote in news:a74o32$1ne7$1 digitaldaemon.com:"Patrick Down" <pdown austin.rr.com> ha scritto nel messaggio news:a72u86$dkt$1 digitaldaemon.com... [...]Yes, this is a problem. Right now I don't think D needs very complicated code for stack unwinding on an exception. But the auto stuff would require a visit to every frame's cleanup section.Could this be made to work with some very simple rules? 1. Determine all your auto varaibles an initialize them to null at the beginning of the function. 2. Make a cleanup section that deletes all the autos at the end of the function. 3. Every assignment to an auto variable is preceeded by a delete of that object.It seems to me a good starting point. But how will you deal with exceptions?inout implies that the parameter could be modified. You could do something like this. SomeObj temp = a; FuncInOut(a); if(temp != a) delete temp;// This is an error can't use auto variables as inout // parameters FuncInOut(a);Why?{ auto Object1 a; Object1 b; b = a; Func(b); // storing the pointer? } // now going out of scope...I don't have a really good solution for this one and there are many of other ways to get in trouble. For example... Object a = new Object; while(...) { auto Object b = a; // a is deleted after one time // thru the loop } The compiler substitution should be changed to something like this... if(a != b) delete a; a = b; Also you can't do this... auto Object a; auto Object b; a = b; Which means this is a problem... auto Object a; auto Object b; Object c; c = a; b = c; There are many of ways this could go wrong. I guess it depends on if a auto delete pointer is worth all the potential programmer error.
Mar 18 2002
Patrick Down wrote:Yes, this is a problem. Right now I don't think D needs very complicated code for stack unwinding on an exception. But the auto stuff would require a visit to every frame's cleanup section.Force-delete doesn't impact the complexity of cleanup code. In any block, you can manually add a finally {} block, which must run when the block exits or an exception is thrown. That's a "hand-made" force-delete. This whole thing is really an issue of whether or not the compiler should include syntax sugar to automatically add one of these cleanup blocks. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 18 2002
I like this idea, but don't think you'd have to specify the storage class explicitly for it to work. I bet the compiler could figure out whether any references to an object created in a given scope could possibly survive past the end of the block. If it did, it'd allocate the object from the heap and later GC it. If no references could possibly survive, it could create the object on the stack and automatically clean it as it goes out of scope. A reference to an object can "survive" a block by having a pointer to it or one of its members passed as a parameter to a function call or directly stored into a nonlocal variable. Yes. I definitely want this. Sean "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C8F869F.F8A5B82A deming-os.org...I think that it would be useful to be able to have a "force-delete" storage class (or some such) for CLASS REFERENCES that would automatically delete the class object when the reference went out of scope. That is, basically, it would be a class object that was NOT garbage collected. This would be useful for things that need to be cleaned up quickly. People have suggested that open files should be cleaned up (to close the file); I run across things in multithreaded programming that are similar. In C++, I do things like this: class Lock; class Locker { private: Lock *lockThis; public: Locker(Lock *lockThis) { this->lockThis = lockThis; lockThis->Lock(); }; ~Locker() { lockThis->Unlock(); }; }; which allows me to write code like this: { Locker lock(collectionObject->lock) ... // do stuff with collection Object } // collectionObject is automatically unlocked when we go out of scope, // either by returning, continuing out of the block, or throwing an exception Obviously, in my style of code, delayed GC is NOT acceptable. You could force the programmer to call delete; as he leaves the block...but the whole point of this object was to make it so the programmer DIDN'T have to remember to unlock everything - it's a failsafe.
Mar 13 2002
"Sean L. Palmer" wrote:I like this idea, but don't think you'd have to specify the storage class explicitly for it to work. I bet the compiler could figure out whether any references to an object created in a given scope could possibly survive past the end of the block. If it did, it'd allocate the object from the heap and later GC it. If no references could possibly survive, it could create the object on the stack and automatically clean it as it goes out of scope. A reference to an object can "survive" a block by having a pointer to it or one of its members passed as a parameter to a function call or directly stored into a nonlocal variable. Yes. I definitely want this.In general, this would work for most applications, but I also have code that passes pointers to Lockers (references in the D mindset) to other functions. Those functions guarantee not to change the lock in the long term, but they do muck with it during their course. So compiler auto-detection is unlikely to work, unless the compiler has VERY aggressive optimization :/ -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Mar 13 2002
Russ Lewis wrote in message <3C8F869F.F8A5B82A deming-os.org>...I think that it would be useful to be able to have a "force-delete" storage class (or some such) for CLASS REFERENCES that would automatically delete the class object when the reference went out of scope. That is, basically, it would be a class object that was NOT garbage collected. This would be useful for things that need to be cleaned up quickly. People have suggested that open files should be cleaned up (to close the file); I run across things in multithreaded programming that are similar. In C++, I do things like this: [snip]I think it's time to unravel the need for a feature and way it was implemented in C++. I think what you want is an encapsulated mechanism that a) has an implicit or explicit context, b) has a entrypoint called on entry to a block, and c) an entreepoint guaranteed to be called on block exit. Note that the semantics of "synchronized" in D and Java have exactly those characteristics, but are builtin rather than programmable. Perhaps the answer is replacement of "synchronized" with an extensible mechanism to allow other and/or additional resource managers to share the semantics. Among other things, this would allow the odd crank to synchronize with two state locks rather than mutexes. Sure would be a nice feature... Among the problems to be solved is argument passing. Although the two forms of "synchronized" take an implicit or explicit argument, the actually monitor is invisible, buried in the implementation. It's fairly clear that any generalization would require a little more infrastructure to be useful.
Mar 22 2002
I suppose the question is "when should an object be deleted?" this could be ... (1) when the procedure / method exits (object goes out of scope) := in which case the compiler could simply add an invisable finally block (2) when a throw occurs := in which case the compiler schedules a garbage collection on all objects in the stack (after all throws are exceptions and need not be fast). (3) when the task / job exits := another garbage collection cycle (think this is already specified in D standard) (4) when an object is overwritten := in the same cases this is trivial - just add "delete <obj>;" before reassignment. - however in a called class this is difficult [void foo( inout a ) { a = new Obj; }] either we check a flag in the object to see if it should be deleted (yuck - slow (has to be done on every new)) or wait until the procedure returns, check if old object == returned object and if not delete old object. Finally we have a problem if the object is referenced outside the procedure, ie. delete must occur on the object even after the force delete command in the procedure has been forgotten. I suggest that if forced deletion is to be included that it works as follows. (1) the object is created specifying forced deletion required (2) the object continues to exist until the procedure it was defined in exits, then the object is deleted - reguardless of any external references - creating such references could be considered an error, though catching this at compile time could be tricky. (3) the object is deleted if a throw is thrown past the procedure - this could be in a finally block or by running a GC cycle (latter option assumes no external references). (4) the object is deleted if it is reassigned within the procedure (5) the object is deleted if it is reassigned within a called procedure - but only after that procedure returns The only other way I can see to achieve this is to use reference counting - though I believe this has been (and should be) ruled out. C 2002/3/25
Mar 25 2002