-
-
Notifications
You must be signed in to change notification settings - Fork 743
Improve scoped implementation #1215
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
Conversation
What's wrong with passing Scoped by ref? |
I'm confused about what you are refering to...? |
Actually nevermind, I used to experiment with scoped before while trying to recreate Qt's stack-based events. For example instantiating from the heap every time you move your mouse to generate a MouseMove event is expensive, so using scoped could do the trick, while keeping event classes polymorphic. But I think I ran into too much problems to make it viable. So, nevermind. :] |
alias classInstanceAlignment!T alignment; | ||
alias _alignUp!alignment aligned; | ||
private alias classInstanceAlignment!T alignment; | ||
private alias _alignUp!alignment aligned; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding private
is not necessary, because they cannot be accessible from outer scope of Eponymous Template.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I though, but Andrei had told me to put them in one of my previous pulls. I'll remove them if they are useless.
I think this is good direction. |
TY for the review. All points addressed. |
Thanks! |
@system auto scoped(Args...)(auto ref Args args) | ||
{ | ||
Scoped result = void; | ||
*cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you add this line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because Scoped_store = void
didn't actually guarantee that Scoped_store
was 0 initialized. writing:
Scoped result; //Fine
but
//@disable this(), init initialialize
Scoped result = Scoped.init;
In this case, result.Scoped_store
was not 0 initialized. This is particularly problematic, because it holds the value of d
, which you need to be 0 initialized.
In the end, I changed result
to be void initialized anyways. The advantage here I guess is that you only initialize the part of Scoped you need initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean this line has no effect as because of line 3356: *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're on to something, but it's the other way around: calculating d
entails calling cast(void*) result.Scoped_payload - result.Scoped_store.ptr
, which calls Scoped_payload
. Scoped payload will make a read to that area to verify alignment, so that variable must be initialized before calling that line.
That said, the line 3356, as you mention, is itself useless, and has always been, since Scoped_payload
will have already done the job. I'll open an improvement to remove it.
I was wondering: I seem to recall you were the one that wrote that code originally. Is any of this code necessary on a 64 bit run-time? Do you think it could be possible to place that code in a version block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Damn, forget my own code...
Sorry, but my code isn't good because memmove
is called without any need at first access to Scoped_payload
. This is the right way to initialize &result.Scoped_store[$ - size_t.sizeof]
(instead of this line and the next one):
void* alignedStore = cast(void*) aligned(cast(size_t) Scoped_store.ptr);
immutable size_t d = alignedStore - Scoped_store.ptr;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is any of this code necessary on a 64 bit run-time?
AFAIK, there is nothing special with 64 bit. If you sure every struct on platform X is properly n-bytes aligned and the class requires m-bytes alignment where m <= n, you just tell compiler that Scoped
struct is m-bytes aligned (not sure about the proper way to do it, maybe U[0]
will help but note about Issue 5332) and branch out alignment code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright. I didn't want to touch that code too much, but I think I fully understand it now, so I'll tweak it as you are suggesting.
Regarding the 64 bit thing, I'm not comfortable with changing anything there, so I'll just leave it as is, and maybe leave a TODO in there or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: #1218
This changes the
scoped(T, Args...)
function, into a template parametrized on T, that returns a function parametrized on Args. EG:The advantages are:
T
(previously, a new definition existed for each and every combination ofArgs
)Finally, I gave
Scoped
an@disabled this()
to prevent our smarter users from trying to build a Scoped usingtypeof
.Also, moved example into a documented unittest.