digitalmars.D.learn - Make sure lifetime of helper structs is less than owning struct
- WebFreak001 (18/18) Nov 15 2021 I have an API with some struct like a file reader. I want to add
- Steven Schveighoffer (4/25) Nov 15 2021 Or maybe just use reference counting to avoid the problem altogether.
- H. S. Teoh (10/31) Nov 15 2021 What about make ByChunk do the construction of the File in its ctor
- Sebastiaan Koppe (24/25) Nov 15 2021 Yes it is. But besides `-dip1000` and `@safe`, it requires the
- WebFreak001 (5/30) Nov 15 2021 awesome, such a simple solution! Also saves me the pain of
- =?UTF-8?Q?Ali_=c3=87ehreli?= (45/78) Nov 15 2021 I don't see how it solves the problem. Sebastiaan Koppe might have
- Imperatorn (2/19) Nov 15 2021 Are you compiling with preview=dip1000?
- =?UTF-8?Q?Ali_=c3=87ehreli?= (7/27) Nov 15 2021 Trying with it produces an error when 'new' is not used:
- Sebastiaan Koppe (8/14) Nov 16 2021 The error is what the OP wanted, so that is expected.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (3/6) Nov 16 2021 Thanks! That's what I missed.
- Imperatorn (3/28) Nov 15 2021 Maybe a candidate for the "d idioms" page
I have an API with some struct like a file reader. I want to add byChunks-like functionality to it, so I'm trying to implement it with a helper struct that implements opApply. I have disabled copying the file reader struct because it cleans up the resources once it goes out of scope, however now I need to temporarily save the resources in the helper struct to be able to read from it. How can I make sure that the foreach helper struct (and with that the copies of the resources) cannot be used once the owning struct goes out of scope? ```d ByChunk helper; { auto file = FileReader(x); helper = file.byChunk; } helper.popFront; // crash - I want the compiler to disallow this ``` is this currently possible or maybe possible with DIP1000?
Nov 15 2021
On 11/15/21 10:56 AM, WebFreak001 wrote:I have an API with some struct like a file reader. I want to add byChunks-like functionality to it, so I'm trying to implement it with a helper struct that implements opApply. I have disabled copying the file reader struct because it cleans up the resources once it goes out of scope, however now I need to temporarily save the resources in the helper struct to be able to read from it. How can I make sure that the foreach helper struct (and with that the copies of the resources) cannot be used once the owning struct goes out of scope? ```d ByChunk helper; { auto file = FileReader(x); helper = file.byChunk; } helper.popFront; // crash - I want the compiler to disallow this ``` is this currently possible or maybe possible with DIP1000?Or maybe just use reference counting to avoid the problem altogether. That's what iopipe/std.io does. -Steve
Nov 15 2021
On Mon, Nov 15, 2021 at 03:56:57PM +0000, WebFreak001 via Digitalmars-d-learn wrote:I have an API with some struct like a file reader. I want to add byChunks-like functionality to it, so I'm trying to implement it with a helper struct that implements opApply. I have disabled copying the file reader struct because it cleans up the resources once it goes out of scope, however now I need to temporarily save the resources in the helper struct to be able to read from it. How can I make sure that the foreach helper struct (and with that the copies of the resources) cannot be used once the owning struct goes out of scope? ```d ByChunk helper; { auto file = FileReader(x); helper = file.byChunk; } helper.popFront; // crash - I want the compiler to disallow this ``` is this currently possible or maybe possible with DIP1000?What about make ByChunk do the construction of the File in its ctor instead? The problem with constructing it separately is that you can't tie the two lifetimes together. But if you create the File while initializing the object, you ensure that the two lifetimes are tied together, and with disable this() you can make sure that ByChunk is not constructible unless the code that opens the File also runs. T -- Computers shouldn't beep through the keyhole.
Nov 15 2021
On Monday, 15 November 2021 at 15:56:57 UTC, WebFreak001 wrote:is this currently possible or maybe possible with DIP1000?Yes it is. But besides `-dip1000` and ` safe`, it requires the use of a pointer: ```D safe: struct ByChunk { FileReader* r; void popFront() {} } struct FileReader { ByChunk byChunk() return scope { return ByChunk(&this); } } void main() { ByChunk helper; { auto file = FileReader(); helper = file.byChunk; // Error: address of variable `file` assigned to `helper` with longer lifetime } helper.popFront; } ```
Nov 15 2021
On Monday, 15 November 2021 at 19:24:56 UTC, Sebastiaan Koppe wrote:On Monday, 15 November 2021 at 15:56:57 UTC, WebFreak001 wrote:awesome, such a simple solution! Also saves me the pain of copying the struct data and avoiding copy constructor and stuff by using a pointer.is this currently possible or maybe possible with DIP1000?Yes it is. But besides `-dip1000` and ` safe`, it requires the use of a pointer: ```D safe: struct ByChunk { FileReader* r; void popFront() {} } struct FileReader { ByChunk byChunk() return scope { return ByChunk(&this); } } void main() { ByChunk helper; { auto file = FileReader(); helper = file.byChunk; // Error: address of variable `file` assigned to `helper` with longer lifetime } helper.popFront; } ```
Nov 15 2021
On 11/15/21 1:58 PM, WebFreak001 wrote:On Monday, 15 November 2021 at 19:24:56 UTC, Sebastiaan Koppe wrote:I don't see how it solves the problem. Sebastiaan Koppe might have intended to allocate the object dynamically with 'new' as well? import std.stdio; safe: struct ByChunk { FileReader* r; ~this() { writeln(__FUNCTION__); } void popFront() { writeln("popFront on ", r); } } struct FileReader { ~this() { writeln(__FUNCTION__, " on ", &this); } ByChunk byChunk() return scope { return ByChunk(&this); } } void main() { ByChunk helper; { auto file = new FileReader(); // <-- NOTE new helper = file.byChunk; } writeln("back in main"); helper.popFront; } This is the current output: deneme.ByChunk.~this back in main popFront on 7F12B377E000 deneme.ByChunk.~this deneme.FileReader.~this on 7F12B377E000 But without that 'new', FileReader is destroyed before popFront: deneme.ByChunk.~this deneme.FileReader.~this on 7FFD8231D4B8 <-- BAD back in main popFront on 7FFD8231D4B8 deneme.ByChunk.~this I think I am misunderstanding something here. :) AliOn Monday, 15 November 2021 at 15:56:57 UTC, WebFreak001 wrote:awesome, such a simple solution! Also saves me the pain of copying the struct data and avoiding copy constructor and stuff by using a pointer.is this currently possible or maybe possible with DIP1000?Yes it is. But besides `-dip1000` and ` safe`, it requires the use of a pointer: ```D safe: struct ByChunk { FileReader* r; void popFront() {} } struct FileReader { ByChunk byChunk() return scope { return ByChunk(&this); } } void main() { ByChunk helper; { auto file = FileReader(); helper = file.byChunk; // Error: address of variable `file` assigned to `helper` with longer lifetime } helper.popFront; } ```
Nov 15 2021
On Monday, 15 November 2021 at 22:27:24 UTC, Ali Çehreli wrote:On 11/15/21 1:58 PM, WebFreak001 wrote:Are you compiling with preview=dip1000?[...]wrote:wrote:[...]the use of[...]variable `file`[...][...]copying the[...]a pointer. I don't see how it solves the problem. Sebastiaan Koppe might have intended to allocate the object dynamically with 'new' as well? [...]
Nov 15 2021
On 11/15/21 2:33 PM, Imperatorn wrote:On Monday, 15 November 2021 at 22:27:24 UTC, Ali =C3=87ehreli wrote:Trying with it produces an error when 'new' is not used: Error: reference to local variable `file` assigned to non-scope=20 parameter `p` calling deneme.ByChunk.opAssign So, I either misunderstand or understand very well :) that a different=20 way of lifetime management (like adding 'new') is needed there. AliOn 11/15/21 1:58 PM, WebFreak001 wrote:=20 Are you compiling with preview=3Ddip1000?[...]wrote:wrote:[...]the use of[...]variable `file`=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 [...][...]copying the[...]a pointer. I don't see how it solves the problem. Sebastiaan Koppe might have=20 intended to allocate the object dynamically with 'new' as well? [...]
Nov 15 2021
On Monday, 15 November 2021 at 22:49:12 UTC, Ali Çehreli wrote:Trying with it produces an error when 'new' is not used: Error: reference to local variable `file` assigned to non-scope parameter `p` calling deneme.ByChunk.opAssignThe error is what the OP wanted, so that is expected. Although, he did ask for it to be on the next line, but this is better since it points exactly to the line where he was escaping a reference to the scoped object.I don't see how it solves the problem. Sebastiaan Koppe might have intended to allocate the object dynamically with 'new' as well?No I didn't. Anything created with new has automatic lifetime. Here the OP wanted to (have the compiler) destroy the FileReader when it left the scope, while disallowing any use after free.
Nov 16 2021
On 11/16/21 12:35 AM, Sebastiaan Koppe wrote:Here the OP wanted to (have the compiler) destroy the FileReader when it left the scope, while disallowing any use after free.Thanks! That's what I missed. Ali
Nov 16 2021
On Monday, 15 November 2021 at 19:24:56 UTC, Sebastiaan Koppe wrote:On Monday, 15 November 2021 at 15:56:57 UTC, WebFreak001 wrote:Maybe a candidate for the "d idioms" pageis this currently possible or maybe possible with DIP1000?Yes it is. But besides `-dip1000` and ` safe`, it requires the use of a pointer: ```D safe: struct ByChunk { FileReader* r; void popFront() {} } struct FileReader { ByChunk byChunk() return scope { return ByChunk(&this); } } void main() { ByChunk helper; { auto file = FileReader(); helper = file.byChunk; // Error: address of variable `file` assigned to `helper` with longer lifetime } helper.popFront; } ```
Nov 15 2021