digitalmars.D - Struct beeing moved around
- Benjamin Thaut (28/28) May 20 2011 The following program:
- Sean Kelly (5/39) May 20 2011 In main above you're declaring a new struct variable t which is =
- so (4/8) May 20 2011 I am confused.
- Sean Kelly (15/21) May 20 2011 default-constructed, then a temporary is created and initialized to 5, =
- so (11/13) May 20 2011 If not, i don't know any other use for constructors, you can do the almo...
- Jonathan M Davis (9/27) May 20 2011 That wouldn't work with
- so (4/17) May 20 2011 Wait a minute, i thought "A a(args, to, constructor)" wasn't allowed in ...
- Jonathan M Davis (11/35) May 20 2011 Hmm. I was sure that it was, but I just tried it, and it won't compile. ...
- Michel Fortin (11/52) May 20 2011 Postblit is a post-copy constructor, not a post-move one. There is no
- Benjamin Thaut (5/53) May 20 2011 What if I need a value type that may be copied, but may not be moved?
- Michel Fortin (6/7) May 20 2011 I don't think that's possible. Why would you want that?
- Benjamin Thaut (32/35) May 20 2011 Lets say you want to implement a GC that is not a Mark & Sweep, and thus...
- Michel Fortin (19/31) May 20 2011 But... is that a real problem or just something you've come up with to
- Benjamin Thaut (14/42) May 21 2011 This is acutally a real problem. I'm currently implementing a Baker GC
- Michel Fortin (18/62) May 22 2011 Not that I know of. There has been some work to make scanning certain
- Sean Kelly (7/15) May 20 2011 5,
- KennyTM~ (3/6) May 20 2011 The assumption is better written in the spec. There's no single mention
- Benjamin Thaut (7/14) May 20 2011 The D spec says at the very top of the struct.html
- kenji hara (4/5) May 20 2011 Yes, this is a bug of 2.052. Temporary object destruction problem was fi...
- Brad Roberts (7/14) May 20 2011
The following program: import std.stdio; struct test { this(this){ writefln("postblit"); } int foo; this(int i){ foo = i; writefln("%x",&foo); } ~this(){ writefln("%x",&foo); } } void main(string[] args){ test t = test(5); } Gives me this output on dmd 2.052: 18fe58 18fe54 Is this a bug in 2.052? (Doesn't happen with 2.053) Why did the location of the struct change? Is there any way to get informed about a struct beeing moved? Is there a way to prevent it? -- Kind Regards Benjamin Thaut
May 20 2011
On May 20, 2011, at 5:14 AM, Benjamin Thaut wrote:The following program: =20 import std.stdio; =20 struct test { this(this){ writefln("postblit"); } =20 int foo; =20 this(int i){ foo =3D i; writefln("%x",&foo); } =20 ~this(){ writefln("%x",&foo); } } =20 void main(string[] args){ test t =3D test(5); } =20 =20 Gives me this output on dmd 2.052: 18fe58 18fe54 =20 Is this a bug in 2.052? (Doesn't happen with 2.053) Why did the location of the struct change? Is there any way to get informed about a struct beeing moved? Is there a way to prevent it?In main above you're declaring a new struct variable t which is = default-constructed, then a temporary is created and initialized to 5, = and then the temporary is copied onto t. It does seem like a postblit = should probably occur in this scenario though.
May 20 2011
On Fri, 20 May 2011 17:30:33 +0300, Sean Kelly <sean invisibleduck.org> wrote:In main above you're declaring a new struct variable t which is default-constructed, then a temporary is created and initialized to 5, and then the temporary is copied onto t. It does seem like a postblit should probably occur in this scenario though.I am confused. There shouldn't be any copying, it is construction.
May 20 2011
On May 20, 2011, at 8:43 AM, so wrote:On Fri, 20 May 2011 17:30:33 +0300, Sean Kelly =<sean invisibleduck.org> wrote:=20default-constructed, then a temporary is created and initialized to 5, = and then the temporary is copied onto t. It does seem like a postblit = should probably occur in this scenario though.In main above you're declaring a new struct variable t which is ==20 I am confused. There shouldn't be any copying, it is construction.If you do the following: MyStruct s; A new instance of MyStruct is be created and default-initialized. = Changing this to: MyStruct s =3D MyStruct(5); Is really just shorthand for: MyStruct s; s =3D MyStruct(5); The compiler can translate this into a single construction (it does in = C++), but I don't know that it's required to.=
May 20 2011
On Fri, 20 May 2011 20:42:26 +0300, Sean Kelly <sean invisibleduck.org> wrote:The compiler can translate this into a single construction (it does in C++), but I don't know that it's required to.If not, i don't know any other use for constructors, you can do the almost same thing with a function. struct A { } A construct() { } void main() { A a = construct(); }
May 20 2011
On Fri, 20 May 2011 20:42:26 +0300, Sean Kelly <sean invisibleduck.org> wrote:That wouldn't work with A a(args, to, constructor); Now, I personally never use that syntax and always use auto a = A(args, to, constructor); but you can't do the first form without a constructor, and even in the second form, you're making it clear that you're spefically constructing a value of that type as opposed to using a some random function which happens to produce that type. But ultimately, constructors are just special functions anyway. - Jonathan M DavisThe compiler can translate this into a single construction (it does in C++), but I don't know that it's required to.If not, i don't know any other use for constructors, you can do the almost same thing with a function. struct A { } A construct() { } void main() { A a = construct(); }
May 20 2011
On Fri, 20 May 2011 21:44:19 +0300, Jonathan M Davis <jmdavisProg gmx.com> wrote:That wouldn't work with A a(args, to, constructor); Now, I personally never use that syntax and always use auto a = A(args, to, constructor); but you can't do the first form without a constructor, and even in the second form, you're making it clear that you're spefically constructing a value of that type as opposed to using a some random function which happens to produce that type. But ultimately, constructors are just special functions anyway. - Jonathan M DavisWait a minute, i thought "A a(args, to, constructor)" wasn't allowed in D. And "test t(5);" gives an error.
May 20 2011
On 2011-05-20 11:52, so wrote:On Fri, 20 May 2011 21:44:19 +0300, Jonathan M Davis <jmdavisProg gmx.com> wrote:Hmm. I was sure that it was, but I just tried it, and it won't compile. I'm confused now. I never use that style though - even with no arguments to the constructor - so that the type's static opCall will be used instead of its init value if it has one. e.g. auto a = A(); instead of A a; So, it's not something that I would ever have tried anyway. But I guess that it was either changed ot some point, or I misremembered about it being legal. - Jonathan M DavisThat wouldn't work with A a(args, to, constructor); Now, I personally never use that syntax and always use auto a = A(args, to, constructor); but you can't do the first form without a constructor, and even in the second form, you're making it clear that you're spefically constructing a value of that type as opposed to using a some random function which happens to produce that type. But ultimately, constructors are just special functions anyway. - Jonathan M DavisWait a minute, i thought "A a(args, to, constructor)" wasn't allowed in D. And "test t(5);" gives an error.
May 20 2011
On 2011-05-20 10:30:33 -0400, Sean Kelly <sean invisibleduck.org> said:On May 20, 2011, at 5:14 AM, Benjamin Thaut wrote:Postblit is a post-copy constructor, not a post-move one. There is no such thing as a post-move constructor in D: structs are assumed to be movable. If the compiler was constructing the struct in place (instead of moving it) it'd be even better, but that's more a question of optimization than semantics. -- Michel Fortin michel.fortin michelf.com http://michelf.com/The following program: import std.stdio; struct test { this(this){ writefln("postblit"); } int foo; this(int i){ foo = i; writefln("%x",&foo); } ~this(){ writefln("%x",&foo); } } void main(string[] args){ test t = test(5); } Gives me this output on dmd 2.052: 18fe58 18fe54 Is this a bug in 2.052? (Doesn't happen with 2.053) Why did the location of the struct change? Is there any way to get informed about a struct beeing moved? Is there a way to prevent it?In main above you're declaring a new struct variable t which is default-constructed, then a temporary is created and initialized to 5, and then the temporary is copied onto t. It does seem like a postblit should probably occur in this scenario though.
May 20 2011
Am 20.05.2011 19:28, schrieb Michel Fortin:On 2011-05-20 10:30:33 -0400, Sean Kelly <sean invisibleduck.org> said:What if I need a value type that may be copied, but may not be moved? -- Kind Regards Benjamin ThautOn May 20, 2011, at 5:14 AM, Benjamin Thaut wrote:Postblit is a post-copy constructor, not a post-move one. There is no such thing as a post-move constructor in D: structs are assumed to be movable. If the compiler was constructing the struct in place (instead of moving it) it'd be even better, but that's more a question of optimization than semantics.The following program: import std.stdio; struct test { this(this){ writefln("postblit"); } int foo; this(int i){ foo = i; writefln("%x",&foo); } ~this(){ writefln("%x",&foo); } } void main(string[] args){ test t = test(5); } Gives me this output on dmd 2.052: 18fe58 18fe54 Is this a bug in 2.052? (Doesn't happen with 2.053) Why did the location of the struct change? Is there any way to get informed about a struct beeing moved? Is there a way to prevent it?In main above you're declaring a new struct variable t which is default-constructed, then a temporary is created and initialized to 5, and then the temporary is copied onto t. It does seem like a postblit should probably occur in this scenario though.
May 20 2011
On 2011-05-20 13:36:58 -0400, Benjamin Thaut <code benjamin-thaut.de> said:What if I need a value type that may be copied, but may not be moved?I don't think that's possible. Why would you want that? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 20 2011
Am 20.05.2011 19:51, schrieb Michel Fortin:On 2011-05-20 13:36:58 -0400, Benjamin Thaut <code benjamin-thaut.de> said:Lets say you want to implement a GC that is not a Mark & Sweep, and thus you can not do the pointer guessing game the current D GC does. So you have to create a reference value type, that registers itself with the GC when it is constructed and deregisteres itself on destruction. This reference type is only to be used inside functions for references that are constructed on the stack. class foo { ... } void bar(){ foo f = new foo(); } would become void bar(){ Ref!foo f = Ref!foo(new foo()); } where Ref is: struct Ref(T){ T m_Ref; alias m_Ref this; this(){ GC.addRoot(&m_Ref); } ~this(){ GC.removeRoot(&m_Ref); } } If there is no garantuee that a struct stays on the same memory location within 1 Stack frame, you pretty much can not implement a other GC unless you hack into the compiler. -- Kind Regards Benjamin ThautWhat if I need a value type that may be copied, but may not be moved?I don't think that's possible. Why would you want that?
May 20 2011
On 2011-05-20 14:46:03 -0400, Benjamin Thaut <code benjamin-thaut.de> said:Am 20.05.2011 19:51, schrieb Michel Fortin:But... is that a real problem or just something you've come up with to argue that a move constructor can be useful? I ask because it looks pretty synthetic: if you're going to call something alike GC.addRoot/GC.removeRoot upon construction and destruction of this smart pointer you could as well implement standard reference counting. And reference counting does not need a move constructor since moving doesn't change the reference count. But this is an interesting topic. I'm currently hacking the compiler to support Objective-C objects. As part of this I want the memory to be managed automatically, which isn't so easy because Objective-C objects have to live in a separate heap. So I'll need to add support for an external memory management system and make it work seamlessly with the D GC. I already know how I'm going to implement it, and it won't require anything like a move constructor. -- Michel Fortin michel.fortin michelf.com http://michelf.com/On 2011-05-20 13:36:58 -0400, Benjamin Thaut <code benjamin-thaut.de> said:[...] If there is no garantuee that a struct stays on the same memory location within 1 Stack frame, you pretty much can not implement a other GC unless you hack into the compiler.What if I need a value type that may be copied, but may not be moved?I don't think that's possible. Why would you want that?
May 20 2011
Am 20.05.2011 22:57, schrieb Michel Fortin:On 2011-05-20 14:46:03 -0400, Benjamin Thaut <code benjamin-thaut.de> said:This is acutally a real problem. I'm currently implementing a Baker GC for the Lisp VM I'm implementing in D 2.0. A Baker GC needs to know exactly where the pointers are located, because it needs to change the pointers during collection. I'm only doing the GC.addRoot/GC.removeRoot for refernces that are allocated on that Stack. Not for every reference. And reference couting is not sufficient, because it does not break cycles. As the GC needs to change the pointers, I would need a move constructor, so I can update the pointers memory location. I'm curious, are there plans that D is going to use something that is not a Mark & Sweep? -- Kind Regards Benjamin ThautAm 20.05.2011 19:51, schrieb Michel Fortin:But... is that a real problem or just something you've come up with to argue that a move constructor can be useful? I ask because it looks pretty synthetic: if you're going to call something alike GC.addRoot/GC.removeRoot upon construction and destruction of this smart pointer you could as well implement standard reference counting. And reference counting does not need a move constructor since moving doesn't change the reference count. But this is an interesting topic. I'm currently hacking the compiler to support Objective-C objects. As part of this I want the memory to be managed automatically, which isn't so easy because Objective-C objects have to live in a separate heap. So I'll need to add support for an external memory management system and make it work seamlessly with the D GC. I already know how I'm going to implement it, and it won't require anything like a move constructor.On 2011-05-20 13:36:58 -0400, Benjamin Thaut <code benjamin-thaut.de> said:[...] If there is no garantuee that a struct stays on the same memory location within 1 Stack frame, you pretty much can not implement a other GC unless you hack into the compiler.What if I need a value type that may be copied, but may not be moved?I don't think that's possible. Why would you want that?
May 21 2011
On 2011-05-21 05:44:58 -0400, Benjamin Thaut <code benjamin-thaut.de> said:Am 20.05.2011 22:57, schrieb Michel Fortin:Not that I know of. There has been some work to make scanning certain parts of the memory precise to reduce false pointer issues, but not for the stack though. <http://d.puremagic.com/issues/show_bug.cgi?id=3463> I don't see many solutions to your problem in the current state of things. Assuming the language doesn't change to accommodate your need you could add one level of indirection for your stack references and update that indirection instead. But that's probably not very satisfactory. I think you should at least fill an enhancement request in bugzilla for move-constructors (or at least the ability to disable moves and force it to do construct/assign/destruct instead) with an explanation of your use case. -- Michel Fortin michel.fortin michelf.com http://michelf.com/On 2011-05-20 14:46:03 -0400, Benjamin Thaut <code benjamin-thaut.de> said:This is acutally a real problem. I'm currently implementing a Baker GC for the Lisp VM I'm implementing in D 2.0. A Baker GC needs to know exactly where the pointers are located, because it needs to change the pointers during collection. I'm only doing the GC.addRoot/GC.removeRoot for refernces that are allocated on that Stack. Not for every reference. And reference couting is not sufficient, because it does not break cycles. As the GC needs to change the pointers, I would need a move constructor, so I can update the pointers memory location. I'm curious, are there plans that D is going to use something that is not a Mark & Sweep?Am 20.05.2011 19:51, schrieb Michel Fortin:But... is that a real problem or just something you've come up with to argue that a move constructor can be useful? I ask because it looks pretty synthetic: if you're going to call something alike GC.addRoot/GC.removeRoot upon construction and destruction of this smart pointer you could as well implement standard reference counting. And reference counting does not need a move constructor since moving doesn't change the reference count. But this is an interesting topic. I'm currently hacking the compiler to support Objective-C objects. As part of this I want the memory to be managed automatically, which isn't so easy because Objective-C objects have to live in a separate heap. So I'll need to add support for an external memory management system and make it work seamlessly with the D GC. I already know how I'm going to implement it, and it won't require anything like a move constructor.On 2011-05-20 13:36:58 -0400, Benjamin Thaut <code benjamin-thaut.de> said:[...] If there is no garantuee that a struct stays on the same memory location within 1 Stack frame, you pretty much can not implement a other GC unless you hack into the compiler.What if I need a value type that may be copied, but may not be moved?I don't think that's possible. Why would you want that?
May 22 2011
On May 20, 2011, at 10:28 AM, Michel Fortin wrote:On 2011-05-20 10:30:33 -0400, Sean Kelly <sean invisibleduck.org> =said:=205,In main above you're declaring a new struct variable t which is default-constructed, then a temporary is created and initialized to =postblitand then the temporary is copied onto t. It does seem like a =such thing as a post-move constructor in D: structs are assumed to be = movable. Ah right. So internal pointers don't work in structs.=should probably occur in this scenario though.=20 Postblit is a post-copy constructor, not a post-move one. There is no =
May 20 2011
On May 21, 11 01:28, Michel Fortin wrote:Postblit is a post-copy constructor, not a post-move one. There is no such thing as a post-move constructor in D: structs are assumed to be movable.The assumption is better written in the spec. There's no single mention of the word "move" in struct.html.
May 20 2011
Am 20.05.2011 20:33, schrieb KennyTM~:On May 21, 11 01:28, Michel Fortin wrote:The D spec says at the very top of the struct.html "A struct is defined to not have an identity; that is, the implementation is free to make bit copies of the struct as convenient." -- Kind Regards Benjamin ThautPostblit is a post-copy constructor, not a post-move one. There is no such thing as a post-move constructor in D: structs are assumed to be movable.The assumption is better written in the spec. There's no single mention of the word "move" in struct.html.
May 20 2011
2011/05/20 21:15 "Benjamin Thaut" <code benjamin-thaut.de>:Is this a bug in 2.052? (Doesn't happen with 2.053)Yes, this is a bug of 2.052. Temporary object destruction problem was fixed in 2.053. Kenji Hara
May 20 2011
On Sat, 21 May 2011, kenji hara wrote:2011/05/20 21:15 "Benjamin Thaut" <code benjamin-thaut.de>:Caution.. SOME of the temp object destruction problems were fixed, but not all. At a minimum, the intersection with exception handling parts are not yet complete. Later, BradIs this a bug in 2.052? (Doesn't happen with 2.053)Yes, this is a bug of 2.052. Temporary object destruction problem was fixed in 2.053. Kenji Hara
May 20 2011