Thread overview | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Sat, Aug 24, 2013 at 02:48:45AM +0200, Andrej Mitrovic wrote: > On Saturday, 24 August 2013 at 00:45:46 UTC, H. S. Teoh wrote: > >Destroy! ;-) > > I won't destroy but I'll say avoid the struct/class keywords and use `scope(this)` instead, it looks nicer and will work easier in generic code. Good point! I'll update the DIP to use scope(this) instead. It does look nicer. And yes, it's important for generic code. :) T -- Nothing in the world is more distasteful to a man than to take the path that leads to himself. -- Herman Hesse |
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On Sat, Aug 24, 2013 at 06:19:25AM +0200, Meta wrote: > "With this extension to scope guards, class and struct destructors will practically not be needed anymore, since scope(this) will take care of cleaning up everything." > > I can't think of an example off the top of my head, but is it really okay to conflate destruction due to an error during construction, and destruction over the regular course of a struct's usage? What if one instance requires different code from the other? Maybe require that scope(this) statements *only* be run if there is an error during construction, while just the destructor will be run normally? If a particular cleanup operation only applies to a ctor failure, you could just use scope(failure) in the ctor, and put the different cleanup code in the dtor. scope(this) is really meant to encapsulate the usual (I think!) case where the same cleanup code applies in both cases. Maybe I was a bit too strong to say dtors won't be needed anymore, but if you leave dtors in, then they can still handle this case. :) T -- May you live all the days of your life. -- Jonathan Swift |
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
On 24/08/13 02:44, H. S. Teoh wrote:
> I've written up a proposal to solve the partially-constructed object
> problem[*] in D in a very nice way by extending scope guards
Converse problem: suppose that you need certain resources to be _created_ in order for the struct to work correctly. Consider:
struct Foo
{
Resource res;
this(int n)
{
res = getResource(n);
}
}
void main()
{
auto foo1 = Foo(10); // Good! Resource is initialized
Foo foo2; // Bad! Resource is uninitialized
}
... where we can probably reasonably assume that getResource is doing some kind of allocation.
Is there any way to handle this needed-at-entry-to-scope requirement, in a similar way to how your DIP handles exit of scope?
|
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | On Saturday, 24 August 2013 at 13:34:06 UTC, Joseph Rushton Wakeling wrote: > On 24/08/13 02:44, H. S. Teoh wrote: >> I've written up a proposal to solve the partially-constructed object >> problem[*] in D in a very nice way by extending scope guards > Is there any way to handle this needed-at-entry-to-scope requirement, in a similar way to how your DIP handles exit of scope? Invariants? |
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On 24/08/13 15:55, Tobias Pankrath wrote:
> Invariants?
Don't they get stripped out in -release code?
|
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | On Saturday, 24 August 2013 at 14:40:36 UTC, Joseph Rushton Wakeling wrote:
> On 24/08/13 15:55, Tobias Pankrath wrote:
>> Invariants?
>
> Don't they get stripped out in -release code?
Yes. But the example code that you presented looked to me like logic/coding errors. Invariants should be good enough here. If you want to pay for the added safety, because you think your code isn't tested well enough at all, you can always compile without debug.
|
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On Sat, 24 Aug 2013 15:55:52 +0200, Tobias Pankrath <tobias@pankrath.net> wrote: > On Saturday, 24 August 2013 at 13:34:06 UTC, Joseph Rushton Wakeling wrote: >> On 24/08/13 02:44, H. S. Teoh wrote: >>> I've written up a proposal to solve the partially-constructed object >>> problem[*] in D in a very nice way by extending scope guards > >> Is there any way to handle this needed-at-entry-to-scope requirement, in a similar way to how your DIP handles exit of scope? > > Invariants? I would also like to mention @disable this(); -- Simen |
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
On 24/08/13 18:21, Simen Kjaeraas wrote:
> I would also like to mention @disable this();
Yes, I know, but suppose that I don't _want_ to disable this() ... ?
Really this is one of those cases where a parameter-free constructor would be useful.
|
August 24, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | I'd seriously *hate* to abuse invariants for that. The job of invariants is to give guarantees about state - not to manage e.g. allocations, creations, cleanups, etc. "Has something properly succeeded and if not is there cleanup needed?" is the job of scope and possibly (but ugly and non-elegantly) exceptions. |
August 26, 2013 Re: DIP44: scope(class) and scope(struct) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | On Sun, Aug 25, 2013 at 12:18:27AM +0200, Tobias Pankrath wrote: > On Saturday, 24 August 2013 at 20:11:14 UTC, H. S. Teoh wrote: > >How would you use RAII to solve this problem? If I have a class: > > > > class C { > > Resource1 res1; > > Resource2 res2; > > Resource3 res3; > > this() { > > ... > > } > > } > > > >How would you write the ctor with RAII such that if it successfully inits res1 and res2, but throws before it inits res3, then only res1 and res2 will be cleaned up? > > Like someone else already proposed: Using a wrapper type W that releases the resources in it's destructor. W.init wouldn't release anything. So by definition (if I recall the rules correctly) every new instance of C would have res3 = Resource3.init prior to it's constructor called. > > Now make sure that a) res3's destructor gets called (check) b) > res3's destructor may be called on Resource3.init. That would be a > new rule similar to 'no internal aliasing' and c) that every > constructor of C either sets res3 to a destructable value or does > not touch it at all ('transactional programming'). [...] But don't you still need to manually cleanup in the case of ctor failure? AFAIK, the dtor is not invoked on the partially-constructed object if the ctor throws. So you'd still have to use scope(failure) to manually release the resource. To prove my point, here is some sample code that (tries to) use RAII to cleanup: import std.stdio; struct Resource { int x = 0; this(int id) { x = id; writefln("Acquired resource %d", x); } ~this() { if (x == 0) writefln("Empty resource, no cleanup"); else writefln("Cleanup resource %d", x); } } struct S { Resource res1; Resource res2; Resource res3; this(int) { res1 = Resource(1); res2 = Resource(2); assert(res1.x == 1); assert(res2.x == 2); throw new Exception("ctor failed!"); res3 = Resource(3); // not reached assert(res3.x == 3); // not reached } } void main() { try { auto s = S(123); } catch(Exception e) { writeln(e.msg); } } Here is the program output: Acquired resource 1 Empty resource, no cleanup Acquired resource 2 Empty resource, no cleanup ctor failed! As you can see, the two resources acquired in the partially-constructed object did NOT get cleaned up. So, RAII doesn't work in this case. The two interspersed cleanups were presumably cause by Resource.init being destructed when res1 and res2 were assigned to. But after being assigned to, res1 and res2's dtors were NOT invoked. So I think my scope(this) idea has some merit, since it will correctly handle this case. :) T -- Many open minds should be closed for repairs. -- K5 user |
Copyright © 1999-2021 by the D Language Foundation