Re: move object from heap to stack
On Wednesday, 19 September 2012 at 21:36:56 UTC, Namespace wrote: I count it to destroy it if it isn't used anymore. What I'm saying though is that when your stacked_obj goes out of scope, it gets destroyed, 100% of the time. The chunk disappears, along with any object inside it. When that happens, it doesn't matter what the count is, whatever is inside chunk MUST be destroyed. I can remove this behaviour but IMO with this you haven't unnecessary use of stack memory. Am I wrong? Yes, because all your stacked_obj have a chunk member variable. The reference count doesn't change that. When you pass by value, a new chunk is created an copied. Your postblit is weird: this(this) { this._use_counter++; this._use_counter = _use_counter; } The way postblit works is that first, the other is memcopyed onto this. Then, postblit modifies the current object. this._use_counter = _use_counter; makes no sense. One more thing: You can't memcopy a class from one place to another, because you don't know if it has a CC or not. You *could* swap the class, which would be safe for the class itself, but not for anything else referencing the class. Furthermore, if I copy the stack object e.g. if I pass it as value parameter to another function/class, I can store it as long as it's needed. Maybe that should be the task of the heap, but I'm not sure. Yes, but technically, you are still passing a copy. Anyways, I re-read scoped's implementation, and classes ARE allocated on the stack. Further more, they can emplace their new object. They can also copy an existing class into them... provided the class gives access to CC. It is not a move, but, IMO, a move would be unsafe anyways. import std.typecons; class A { this(){} this(int){} this(A){} } void main() { auto sa = scoped!A(new A()); auto sb = scoped!A(5); } I'm not entirely.
Re: move object from heap to stack
On Thursday, 20 September 2012 at 08:10:36 UTC, Namespace wrote: You're right. This is my next try: http://dpaste.dzfl.pl/02b32d33 Do you have anything else to say? :) I think it looks good, but I'm unsure about move, or allowing pass by value: Classes can't be memcopied the way structs can: Class may have default constructors, or copy constructors, which would be totally ignored by a memcopy. For example, if your class had a RefCounted member, its postblit would never be called, and it would then be over destroyed: class A { RefCounted!int rf; this() { rf.RefCounted.ensureInitialized(); rf = 5; } } void main() { A a = new A(); OnStack!A osa = OnStack!A.move(a); } core.exception.InvalidMemoryOperationError Here, osa makes a binary copy of the RefCounted, so the count stays at 1. Then, when osa is destroyed, it deletes the RefCounted's store. However, when a is destroyed, it still has a pointer to the (deleted) store, creating the Error... I think move has to go, because classes are just not moveable. pass by value can stay, if and only if, T gives a copy constructor. Or NO constructors (in which case a memcopy should be the same as a default copy).
Re: move object from heap to stack
Am Thu, 20 Sep 2012 10:11:37 +0200 schrieb Namespace rswhi...@googlemail.com: You're right. This is my next try: http://dpaste.dzfl.pl/02b32d33 Do you have anything else to say? :) I think it shouldn't be possible to copy an OnStack struct. The destructor is run for every copy, but the constructor was run only once. So if a class keeps external references (e.g. file handles) and closes those handles in the destructor, making a copy would result in the destructor running twice and therefore closing the same handle twice. I think the usage of a OnStack struct must be quite limited to be safe: { auto a = OnStack!(A)(); //allocate in scope a.doSomething(); //Calling members is fine //a.get and a must not escape this scope (I guess we can't guarantee //that without compiler help?) //passing a.get to a function is valid, as long as the function //doesn't keep a reference (the function parameter must be marked //with scope) someMethod(a.get); //As a shouldn't be copied, an OnStack can't be passed to another //function. //no copies for OnStack allowed //destroy at end of scope } Those rules are pretty strict, but maybe that's the only way to have a safe OnStack. Maybe I forgot some detail and those rules aren't even strict enough.
Re: move object from heap to stack
Am Thu, 20 Sep 2012 12:06:28 +0200 schrieb monarch_dodra monarchdo...@gmail.com: On Thursday, 20 September 2012 at 08:10:36 UTC, Namespace wrote: You're right. This is my next try: http://dpaste.dzfl.pl/02b32d33 Do you have anything else to say? :) I think it looks good, but I'm unsure about move, or allowing pass by value: Classes can't be memcopied the way structs can: Class may have default constructors, or copy constructors, which would be totally ignored by a memcopy. For example, if your class had a RefCounted member, its postblit would never be called, and it would then be over destroyed: class A { RefCounted!int rf; this() { rf.RefCounted.ensureInitialized(); rf = 5; } } void main() { A a = new A(); OnStack!A osa = OnStack!A.move(a); } core.exception.InvalidMemoryOperationError Here, osa makes a binary copy of the RefCounted, so the count stays at 1. Then, when osa is destroyed, it deletes the RefCounted's store. However, when a is destroyed, it still has a pointer to the (deleted) store, creating the Error... I think move has to go, because classes are just not moveable. pass by value can stay, if and only if, T gives a copy constructor. Or NO constructors (in which case a memcopy should be the same as a default copy). http://dlang.org/struct.html D classes do not really have copy constructors. You could assume that if a constructor has only one argument and it's of the same type as the class, it's a copy constructor. But that's a pure convention then, nothing than could be enforced in any way. Copying classes is dangerous, and problems can also happen without constructors: -- class A { void* handle; ~this() { if(handle) free(handle); } } { auto a = OnStack!A(); a.handle = someHandle; auto b = a; //copy } //end of scope, someHandle is freed twice -- This can even happen if the class does not keep any reference types. The example would also be valid with a file handle (uint).
Re: move object from heap to stack
So I should disable the copy ctor (@disable this(this)) and drop move, right? As you can See if I pass a OnStack to function/class i'm using .get all the Time. The only other method IMO would be to pass it as OnStack by value and Store it in the other class also as OnStack, right? @bearophiole: just to Know if something lile this is possible.
Re: move object from heap to stack
On Thursday, 20 September 2012 at 12:32:03 UTC, Namespace wrote: So I should disable the copy ctor (@disable this(this)) and drop move, right? Yes, but at that point, what you have is scoped!T re-implemented :/ As you can See if I pass a OnStack to function/class i'm using .get all the Time. You could alias get this. This way, your OnStack will call cast as a T implicitly. Again, this is what scoped!T does. The only other method IMO would be to pass it as OnStack by value and Store it in the other class also as OnStack, right? Yes, but that would require a copy contructor this(this), which we have actually ruled out. You can pass the T itself thanks to the implicit cast to T, but you can't pass an actual OnStack object.
Re: move object from heap to stack
On Thursday, 20 September 2012 at 14:02:01 UTC, monarch_dodra wrote: On Thursday, 20 September 2012 at 12:32:03 UTC, Namespace wrote: So I should disable the copy ctor (@disable this(this)) and drop move, right? Yes, but at that point, what you have is scoped!T re-implemented :/ As you can See if I pass a OnStack to function/class i'm using .get all the Time. You could alias get this. This way, your OnStack will call cast as a T implicitly. Again, this is what scoped!T does. The only other method IMO would be to pass it as OnStack by value and Store it in the other class also as OnStack, right? Yes, but that would require a copy contructor this(this), which we have actually ruled out. You can pass the T itself thanks to the implicit cast to T, but you can't pass an actual OnStack object. http://dpaste.dzfl.pl/edit/361a54eb With [code] @disable this(this); [/code] this don't work (as expected). But with the copy ctor but without .get you earn a segmentation fault (as you can see). So you can disable the copy ctor but without using .get you're not get what you want. Even with scoped, but scoped's getter name is too long.
Re: move object from heap to stack
On Thursday, 20 September 2012 at 14:09:29 UTC, Namespace wrote: http://dpaste.dzfl.pl/edit/361a54eb With [code] @disable this(this); [/code] this don't work (as expected). But with the copy ctor but without .get you earn a segmentation fault (as you can see). So you can disable the copy ctor but without using .get you're not get what you want. Even with scoped, but scoped's getter name is too long. Wrong link.
Re: move object from heap to stack
On Thursday, 20 September 2012 at 14:15:23 UTC, monarch_dodra wrote: On Thursday, 20 September 2012 at 14:09:29 UTC, Namespace wrote: http://dpaste.dzfl.pl/edit/361a54eb With [code] @disable this(this); [/code] this don't work (as expected). But with the copy ctor but without .get you earn a segmentation fault (as you can see). So you can disable the copy ctor but without using .get you're not get what you want. Even with scoped, but scoped's getter name is too long. Wrong link. Try this: http://dpaste.dzfl.pl/9247af54
Re: move object from heap to stack
On Thursday, 20 September 2012 at 15:04:48 UTC, Namespace wrote: On Thursday, 20 September 2012 at 14:15:23 UTC, monarch_dodra wrote: On Thursday, 20 September 2012 at 14:09:29 UTC, Namespace wrote: http://dpaste.dzfl.pl/edit/361a54eb With [code] @disable this(this); [/code] this don't work (as expected). But with the copy ctor but without .get you earn a segmentation fault (as you can see). So you can disable the copy ctor but without using .get you're not get what you want. Even with scoped, but scoped's getter name is too long. Wrong link. Try this: http://dpaste.dzfl.pl/9247af54 What did you expect? You are passing your OnStack by value. In this particular case, you are over destroying your OnStack!B, which in turn over destroyes his _a. Reactivate the disable, and you'll see the problem blatantly: http://dpaste.dzfl.pl/9e873033 /home/c192/c104.d(102): Error: struct c104.OnStack!(A).OnStack is not copyable because it is annotated with @disable The problem with implicit cast is that *sometimes* you think it does it, but in fact, it doesn't. Here, it didn't. The opCall expects Arg... so if you give it an OnStack, it accepts an OnStack. If you want it to take a T, you have to specify it, either in the template, or with get, or with a cast. Here is a cast version, with this(this) disabled: http://dpaste.dzfl.pl/837f44a9
Re: move object from heap to stack
I expect nothing, my only intention was to show you, that this cannot work. But that it works with an explicit cast is very impressive. I thought the alias this does it automatically. I'm learning too. ;)
move object from heap to stack
Is that possible? I can initialize an object with scope or, in feature, with scoped, directly on the stack but is it also possible to move an existing object from the heap to the stack?
Re: move object from heap to stack
On Wednesday, 19 September 2012 at 13:32:42 UTC, Namespace wrote: Is that possible? I can initialize an object with scope or, in feature, with scoped, directly on the stack but is it also possible to move an existing object from the heap to the stack? I tried this: http://dpaste.dzfl.pl/2955ff41 But as you can see in line 25/26, after I destroyed the heap object, the stack object seems to be corrupted.
Re: move object from heap to stack
On Wed, 19 Sep 2012 15:45:21 +0200, Namespace rswhi...@googlemail.com wrote: On Wednesday, 19 September 2012 at 13:32:42 UTC, Namespace wrote: Is that possible? I can initialize an object with scope or, in feature, with scoped, directly on the stack but is it also possible to move an existing object from the heap to the stack? I tried this: http://dpaste.dzfl.pl/2955ff41 But as you can see in line 25/26, after I destroyed the heap object, the stack object seems to be corrupted. The problem here is that A.sizeof returns the size of the reference, not the instance. Instead you should use __traits(classInstanceSize, A). Also, do have a look at the internals of std.typecons.scoped, it likely contains some good ideas. -- Simen
Re: move object from heap to stack
Thanks, I will use __traits(classInstanceSize, A); But it does not work either.
Re: move object from heap to stack
On Wednesday, 19 September 2012 at 17:08:28 UTC, monarch_dodra wrote: On Wednesday, 19 September 2012 at 14:16:31 UTC, Namespace wrote: Thanks, I will use __traits(classInstanceSize, A); But it does not work either. This is because classes are already pointers. when you write a, you are getting the address of pointer itself. So when you memcopy, don't use a, but use cast(void*)a. What you were currently doing was memcopying the pointer to a into your chunk. From there, since you were casting to A*, everything worked and was legal, but you still only had 1 class intance. Your destroying that instance made your ap crash. this works: http://dpaste.dzfl.pl/8ba1f457 I forget this. Thank you! IMO something like this should exist in phobos. A more flexible version of scoped also.
Re: move object from heap to stack
Result: http://dpaste.dzfl.pl/24988d8f
Re: move object from heap to stack
On Wednesday, 19 September 2012 at 19:24:34 UTC, Namespace wrote: Result: http://dpaste.dzfl.pl/24988d8f I like it, but how can something placed on the stack be reference counted? The chunk is also placed on the stack, so it doesn't really make sense to me: When the object goes out of scope, the chunk goes, regardless of ref count. I think you should ditch the whole ref count thing. You'll also have to be aware of the dangers of putting a class instance on the stack: main() { A a; { stacked_obj!A so; so.gen; a = so.get; } a.print(); //-- undefined, with or without reference count } IE: Big red comment you should NEVER extract an instance from the stack.