Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example of how to use scoped member variable #1644

Merged
merged 1 commit into from Dec 16, 2013

Conversation

brad-anderson
Copy link
Member

The syntax for how to do this has changed several times so it's time to document the right way to do it.

@ghost
Copy link

ghost commented Oct 15, 2013

Note:

import std.typecons;

class A
{
    this(int) { }
}

struct S
{
    typeof(scoped!A()) a;  // fails!
}

We should just make Scoped a non-voldemort struct in module scope. I really don't know why someone moved it inside.

@ghost
Copy link

ghost commented Oct 18, 2013

@monarchdodra: Any objections in moving Scoped outside to be a non-voldemort so it's usable as a field? I guess the use-case would be a simpler alternative to emplace. Alternatively we could introduce a scoped-alternative which can be used for fields (perhaps a mixin template?).

@DmitryOlshansky
Copy link
Member

@AndrejMitrovic AFAIK it was just a religious zeal with voldemort types. Scoped could be very useful to cut down on number of indirections inside a class, it also safe unlike create on stack is.

@JakobOvrum
Copy link
Member

I'd also like to see Scoped or an equivalent as a public type usable for embedding classes in-place. I tried doing this while at the same time removing the runtime realignment code by replacing it with align(n), but apparently align(n) on a struct definition doesn't actually affect codegen at all yet (I was under the impression that it had been fixed).

If Scoped is made public, its assignment and/or copy semantics must be well-defined.

I think an option is to keep Scoped opaque and limited, but introduce a new Embed that is public and supports the necessary primitives.

@monarchdodra
Copy link
Collaborator

Any objections in moving Scoped outside to be a non-voldemort so it's usable as a field?

My point of view is that Voldermort (or more generally, private types) only make sense for adaptor, or operations with state. I'm thinking chain, splitter, filter etc... These really only exist as results of operation, and not really as objects that carry their own definition.

This is not the case of things like RefCounted or Scoped, however (IMO), and I see no reason for Scope for either to be so. RefCounted isn't, so neither should Scoped

The real issue though, was how dangerous scoped's semantics are, in particular, it's constructions and destruction semantics: A Scoped must be constructed, no more than once, and must be destroyed, exactly once. They can't be default initialized nor posblitted.

So I'm OK if we allow them as members of aggregates, but we really need to make sure they are properlly documented, and explain the hows, why, and dangers of using them.

Off topic: Why is Scoped_payload inout, when it mutates its buffer?

@monarchdodra
Copy link
Collaborator

@AndrejMitrovic AFAIK it was just a religious zeal with voldemort types. Scoped could be very useful to cut down on number of indirections inside a class, it also safe unlike create on stack is.

I think part of the issue was the diffuclty of definining initialization semantics for it. Making it voldermort allowed us to bail on answering that question.

Also, I don't see how it could be any safer, when you can place said structs on the stack? It's an escaping reference no matter how you see it.

ALso, I'm unsure about the "number of indirections". It keeps locality, yes, but to call something on the class, you have to first dereference it, and then call the method on the acquired class reference. I'm not sure there's any way out of it for calling member methods, but it's redundant for accessing members.

This is getting off topic, but I think Scoped's design would be improved with an opDispatch, instead of an alias this: It would allow everything it currently allows, with some potentially better performance, while protecting the user from unexpected implicit cast to class instance.

This post is relevant: http://forum.dlang.org/thread/xfbeberchntuqrqasfdn@forum.dlang.org?page=2#post-uyjavwotvbiugppfzbgs:40forum.dlang.org

@DmitryOlshansky
Copy link
Member

@monarchdodra

Look at typically Javaescue D code:

class Books{ ... }
class Shelf{ Books books; ... }

You walk 2 memory location to get at books data. With scoped the data is "right there" inside of the Shelf.
2nd point is that class containing Scoped as member is perfectly safe as the memory is (as usual) assumed to be on the GC heap.
3rd is that class instances are never copied implicitly but (may be) moved. Any copies are via user-defined methods so no worries of postblit madness.

4th if you embded something into a struct, it's again not any worse the the usual struct. Simply because it's prohibited by D spec to store any internal pointers (including to the Scoped part) inside of structs, in the end it makes for the exactly the same "do not escape references to the stack-allocated structs" as w/o Scoped involved.

@ghost
Copy link

ghost commented Oct 20, 2013

Unfortunately opDispatch has its own set of issues. I don't think you can currently achieve perfect forwarding with it.

@monarchdodra
Copy link
Collaborator

So, are we deciding to make Scoped a non-voldermort type then? I think that's the best solution. @eco ?

@brad-anderson
Copy link
Member Author

I agree that'd be the ideal solution. I'll defer to someone else who knows more about the issues involved to actually make the change though. Feel free to close this.

@MartinNowak
Copy link
Member

I tried doing this while at the same time removing the runtime realignment code by replacing it with align(n), but apparently align(n) on a struct definition doesn't actually affect codegen at all yet (I was under the impression that it had been fixed).

What's your problem here? Align on struct does work.

@MartinNowak
Copy link
Member

The real issue though, was how dangerous scoped's semantics are, in particular, it's constructions and destruction semantics: A Scoped must be constructed, no more than once, and must be destroyed, exactly once. They can't be default initialized nor posblitted.

Make it non-copyable?

@monarchdodra
Copy link
Collaborator

What's your problem here? Align on struct does work.

For aligning on the heap. Not on the stack. Also, align(N) where N is not an actual integral literal is not legal either: https://d.puremagic.com/issues/show_bug.cgi?id=9766

Make it non-copyable?

Yes, it's not that big of an issue actually.

@monarchdodra
Copy link
Collaborator

The pull as is is LGTM.

monarchdodra added a commit that referenced this pull request Dec 16, 2013
Add example of how to use scoped member variable
@monarchdodra monarchdodra merged commit 899604e into dlang:master Dec 16, 2013
@MartinNowak
Copy link
Member

Make it non-copyable?
Yes, it's not that big of an issue actually.

Moving Scoped!T would break inner class pointers, so there should be a runtime check to catch this.
Not sure where though, postblit wouldn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants