digitalmars.D.learn - is struct delete deterministic? (cf used in Unique)
- Timothee Cour via Digitalmars-d-learn (9/9) Mar 07 2015 I'm a little confused about the following:
- weaselcat (8/22) Mar 07 2015 structs are allocated on the stack(unless instantiated with new),
- Timothee Cour via Digitalmars-d-learn (10/29) Mar 07 2015 To clarify, I'm only asking about a struct allocated via new.
- weaselcat (14/62) Mar 08 2015 Unique!T allocates via new, but itself is meant to be allocated
- Jonathan M Davis via Digitalmars-d-learn (23/31) Mar 08 2015 Yes, delete is deterministic. It's basically the same as what you get in...
- Jonathan M Davis via Digitalmars-d-learn (13/44) Mar 08 2015 I would point out though that until recently, the GC never ran the
- Timothee Cour via Digitalmars-d-learn (4/64) Mar 08 2015 Thanks for you answers, however this last sentence worries me. According...
- Jonathan M Davis via Digitalmars-d-learn (21/34) Mar 08 2015 Previously, struct destructors were _never_ run by the GC, because it
I'm a little confused about the following: clear,delete,destroy. My understanding is that clear is deprecated and delete is planned to be deprecated, so we should only ever use destroy (which deterministic calls the destructor but doesn't release memory). Unique uses delete however in the destructor. Is that still guaranteeing deterministic destruction when the uniqued element is either a class or struct? (ie if the destructor has a file handle resource, will it be deterministically freed?)
Mar 07 2015
On Saturday, 7 March 2015 at 23:48:39 UTC, Timothee Cour wrote:I'm a little confused about the following: clear,delete,destroy. My understanding is that clear is deprecated and delete is planned to be deprecated, so we should only ever use destroy (which deterministic calls the destructor but doesn't release memory). Unique uses delete however in the destructor. Is that still guaranteeing deterministic destruction when the uniqued element is either a class or struct? (ie if the destructor has a file handle resource, will it be deterministically freed?)structs are allocated on the stack(unless instantiated with new), and call their destructor when you leave their scope. Unique still guarantees deterministic destruction because it's wrapped around a struct, it's a fairly common 'D idiom' I'd say(i.e, look at how File is implemented - D's runtime and standard library are surprisingly well documented and easy to read.) I'm not sure why Unique uses delete, might just be bitrot.
Mar 07 2015
To clarify, I'm only asking about a struct allocated via new. Unique!T is wrapped around a struct, but it allocates a struct T via 'new', so my question still holds: does 'delete t' (where t is a struct allocated via new) guarantee deterministic destruction? I'm guessing yes, otherwise Unique would be broken, but where is that specified in the docs? And if delete is to be deprecated (according to the docs), what is the correct way to do that (despite fact that Unique relies on delete). On Sat, Mar 7, 2015 at 4:02 PM, weaselcat via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:On Saturday, 7 March 2015 at 23:48:39 UTC, Timothee Cour wrote:I'm a little confused about the following: clear,delete,destroy. My understanding is that clear is deprecated and delete is planned to be deprecated, so we should only ever use destroy (which deterministic calls the destructor but doesn't release memory). Unique uses delete however in the destructor. Is that still guaranteeing deterministic destruction when the uniqued element is either a class or struct? (ie if the destructor has a file handle resource, will it be deterministically freed?)structs are allocated on the stack(unless instantiated with new), and call their destructor when you leave their scope. Unique still guarantees deterministic destruction because it's wrapped around a struct, it's a fairly common 'D idiom' I'd say(i.e, look at how File is implemented - D's runtime and standard library are surprisingly well documented and easy to read.) I'm not sure why Unique uses delete, might just be bitrot.
Mar 07 2015
On Sunday, 8 March 2015 at 01:20:57 UTC, Timothee Cour wrote:To clarify, I'm only asking about a struct allocated via new. Unique!T is wrapped around a struct, but it allocates a struct T via 'new', so my question still holds: does 'delete t' (where t is a struct allocated via new) guarantee deterministic destruction? I'm guessing yes, otherwise Unique would be broken, but where is that specified in the docs? And if delete is to be deprecated (according to the docs), what is the correct way to do that (despite fact that Unique relies on delete). On Sat, Mar 7, 2015 at 4:02 PM, weaselcat via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:Unique!T allocates via new, but itself is meant to be allocated on the stack. When it leaves the scope it calls delete on its contents(if they're still valid - i.e, haven't been moved to a different Unique!T) delete guarantees deterministic destruction because structs guarantee deterministic destruction, and Unique!T itself is a struct. http://dlang.org/cpptod.html#raii To answer your questions, 1. Yes, Unique!T guarantees deterministic destruction of T(unless there are bugs I'm unaware of.) 2. It's on the deprecated page. http://dlang.org/deprecate.html#deleteOn Saturday, 7 March 2015 at 23:48:39 UTC, Timothee Cour wrote:I'm a little confused about the following: clear,delete,destroy. My understanding is that clear is deprecated and delete is planned to be deprecated, so we should only ever use destroy (which deterministic calls the destructor but doesn't release memory). Unique uses delete however in the destructor. Is that still guaranteeing deterministic destruction when the uniqued element is either a class or struct? (ie if the destructor has a file handle resource, will it be deterministically freed?)structs are allocated on the stack(unless instantiated with new), and call their destructor when you leave their scope. Unique still guarantees deterministic destruction because it's wrapped around a struct, it's a fairly common 'D idiom' I'd say(i.e, look at how File is implemented - D's runtime and standard library are surprisingly well documented and easy to read.) I'm not sure why Unique uses delete, might just be bitrot.
Mar 08 2015
On Saturday, March 07, 2015 17:20:49 Timothee Cour via Digitalmars-d-learn wrote:To clarify, I'm only asking about a struct allocated via new. Unique!T is wrapped around a struct, but it allocates a struct T via 'new', so my question still holds: does 'delete t' (where t is a struct allocated via new) guarantee deterministic destruction? I'm guessing yes, otherwise Unique would be broken, but where is that specified in the docs? And if delete is to be deprecated (according to the docs), what is the correct way to do that (despite fact that Unique relies on delete).Yes, delete is deterministic. It's basically the same as what you get in C++ except that it's using the GC heap and therefore is not safe. delete is supposed to have been deprecated but has not been yet (mostly because no one has gotten around to doing it). If you're using the GC heap and want to destroy an object, that's what destroy is for - but it doesn't free the memory, because that's not safe. You can free the memory with core.memory.GC.free, but you have to have destroyed the object first, since free just frees memory. But that's just duplicating what delete does, so it's still unsafe. What's generally considered the correct way to deal with manual memory management involves allocating using C's malloc, constructing via emplace, and then using destroy and C's free to destroy the object and free its memory when you're done. But that's way more of a pain then using new and then delete, which is probably part of why some folks still use delete (in the case of Unique though, I expect that it's just because it's been around a while). Hopefully, the standard allocator stuff will make it as simple as using new and delete though - e.g. something like auto ptr = alloc.make!Myobj(arg1, arg2); alloc.free(ptr); but the standard allocator stuff isn't currently far enough along yet for us to be at that point unfortunately. - Jonathan M Davis
Mar 08 2015
On Sunday, March 08, 2015 04:13:28 Jonathan M Davis via Digitalmars-d-learn wrote:On Saturday, March 07, 2015 17:20:49 Timothee Cour via Digitalmars-d-learn wrote:I would point out though that until recently, the GC never ran the destructors for structs on the heap, because it didn't have the type information to do it. So, if you did auto s = new MyStruct; its destructor never ran, even if the GC collected it (which it's not guaranteed to do with any memory). But I don't know if the destructor was run if you expliictly called delete on the pointer to the struct. However, there has recently been work done to make it so that struct destructors on the heap _are_ run when a struct is collected by the GC, so the situation there is improving, and if delete didn't call the destructor before, it probably will with the next release. - Jonathan M DavisTo clarify, I'm only asking about a struct allocated via new. Unique!T is wrapped around a struct, but it allocates a struct T via 'new', so my question still holds: does 'delete t' (where t is a struct allocated via new) guarantee deterministic destruction? I'm guessing yes, otherwise Unique would be broken, but where is that specified in the docs? And if delete is to be deprecated (according to the docs), what is the correct way to do that (despite fact that Unique relies on delete).Yes, delete is deterministic. It's basically the same as what you get in C++ except that it's using the GC heap and therefore is not safe. delete is supposed to have been deprecated but has not been yet (mostly because no one has gotten around to doing it). If you're using the GC heap and want to destroy an object, that's what destroy is for - but it doesn't free the memory, because that's not safe. You can free the memory with core.memory.GC.free, but you have to have destroyed the object first, since free just frees memory. But that's just duplicating what delete does, so it's still unsafe. What's generally considered the correct way to deal with manual memory management involves allocating using C's malloc, constructing via emplace, and then using destroy and C's free to destroy the object and free its memory when you're done. But that's way more of a pain then using new and then delete, which is probably part of why some folks still use delete (in the case of Unique though, I expect that it's just because it's been around a while). Hopefully, the standard allocator stuff will make it as simple as using new and delete though - e.g. something like auto ptr = alloc.make!Myobj(arg1, arg2); alloc.free(ptr); but the standard allocator stuff isn't currently far enough along yet for us to be at that point unfortunately.
Mar 08 2015
On Sun, Mar 8, 2015 at 4:36 AM, Jonathan M Davis via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:On Sunday, March 08, 2015 04:13:28 Jonathan M Davis via Digitalmars-d-learn wrote:Thanks for you answers, however this last sentence worries me. According to it there's no guarantee then?On Saturday, March 07, 2015 17:20:49 Timothee Cour viaDigitalmars-d-learn wrote:'new',To clarify, I'm only asking about a struct allocated via new. Unique!T is wrapped around a struct, but it allocates a struct T viaallocatedso my question still holds: does 'delete t' (where t is a structC++via new) guarantee deterministic destruction? I'm guessing yes, otherwise Unique would be broken, but where is that specified in the docs? And if delete is to be deprecated (according to the docs), what is the correct way to do that (despite fact that Unique relies on delete).Yes, delete is deterministic. It's basically the same as what you get inexcept that it's using the GC heap and therefore is not safe. delete is supposed to have been deprecated but has not been yet (mostly because noonehas gotten around to doing it). If you're using the GC heap and want to destroy an object, that's what destroy is for - but it doesn't free the memory, because that's not safe. You can free the memory with core.memory.GC.free, but you have to have destroyed the object first, since free just frees memory. But that's just duplicating what delete does, so it's still unsafe. What's generally considered the correct way to deal with manual memory management involves allocating using C's malloc, constructing viaemplace,and then using destroy and C's free to destroy the object and free its memory when you're done. But that's way more of a pain then using new and then delete, which is probably part of why some folks still use delete(inthe case of Unique though, I expect that it's just because it's beenarounda while). Hopefully, the standard allocator stuff will make it as simpleasusing new and delete though - e.g. something like auto ptr = alloc.make!Myobj(arg1, arg2); alloc.free(ptr); but the standard allocator stuff isn't currently far enough along yetfor usto be at that point unfortunately.I would point out though that until recently, the GC never ran the destructors for structs on the heap, because it didn't have the type information to do it. So, if you did auto s = new MyStruct; its destructor never ran, even if the GC collected it (which it's not guaranteed to do with any memory). But I don't know if the destructor was run if you expliictly called delete on the pointer to the struct.However, there has recently been work done to make it so that struct destructors on the heap _are_ run when a struct is collected by the GC, so the situation there is improving, and if delete didn't call the destructor before, it probably will with the next release. - Jonathan M Davis
Mar 08 2015
On Sunday, March 08, 2015 14:04:52 Timothee Cour via Digitalmars-d-learn wrote:On Sun, Mar 8, 2015 at 4:36 AM, Jonathan M Davis via Digitalmars-d-learn <Previously, struct destructors were _never_ run by the GC, because it didn't have the required type information. What I don't know is whether delete called a struct's destructor or not. But if it didn't, then it never did. There was no maybe about it. Either it always did, or it never did. I just don't know which it is, because I haven't really used delete, and I don't recall anyone discussing whether delete had the same problem that the GC does when it runs (I'd guess not, but I'd have to test it). With the upcoming release, however, it's been changed so that struct destructors _do_ get called by the GC, which would presumably make it so that delete calls the struct's destructor if it didn't before. I guess that I can just revert my dmd to an older release and see what happens there (I'm normally sitting on master)... Yeah. delete calls the struct's destructor even though the GC doesn't. And there's nothing non-deterministic about it. The GC isn't guaranteed to collect something (so even with the recent changes with regards to structs, there's still no guarantee that their destructors will be run), but delete is, since you're explicitly telling it to. It was just a question of whether delete had the same problem that the GC did and couldn't run the struct's destructor. But fortunately, that doesn't seem to be the case. - Jonathan M DavisI would point out though that until recently, the GC never ran the destructors for structs on the heap, because it didn't have the type information to do it. So, if you did auto s = new MyStruct; its destructor never ran, even if the GC collected it (which it's not guaranteed to do with any memory). But I don't know if the destructor was run if you expliictly called delete on the pointer to the struct.Thanks for you answers, however this last sentence worries me. According to it there's no guarantee then?
Mar 08 2015