Skip to content

Optimize C++/WinRT implementation signatures#512

Merged
kennykerr merged 3 commits into
masterfrom
kennkerr-async2
Jul 11, 2019
Merged

Optimize C++/WinRT implementation signatures#512
kennykerr merged 3 commits into
masterfrom
kennkerr-async2

Conversation

@kennykerr

Copy link
Copy Markdown
Contributor

The default implementation signatures generated by cppwinrt for a component weren't always ideal. Specifically, properties always took their single argument by value thus forcing a copy. Developers can easily fix this in their implementation but many not think to do so. This update fixes that, but I'll add a bit of an explanation for the internal logic in case it's not that obvious.

The is_async helper decides whether a given method (or property) is async. Primarily this is about detecting whether the method returns one of the WinRT async interfaces, but it is also used under certain conditions for properties, which are not async in that sense. The reason for the former is obvious, but for the latter it can be a little subtle.

WinRT parameter passing conventions include the notion that input parameters of collection types may be read or copied but should not be stored directly since this would lead to instability as the collection is shared by the caller and callee. The exception to this rule is property setters where the callee may simply store a reference to the collection. The collection thus becomes async in the sense that it is expected to remain valid beyond the duration of the call.

Coming back to C++/WinRT, the language projection optimizes for various input parameter bindings. This allows for things like efficiently calling a WinRT method expecting an IVector<int> with a local std::vector<int>. This is possible because the implementation of IVector<int> produced in these cases has special invalidation logic that will prevent the IVector<int> from being used beyond the duration of the call. Of course, if the method is known to be async then this logic should not be provided and the caller should instead be required to provide an implementation that is not locally bound. All of this is handled automatically by C++/WinRT under the hood and relies on this is_async function to determine when to apply this policy.

The update here simply ensures that this policy of treating properties as async is not applied to an implementation since the optimization only affects the call site. The callee doesn't know anything about how the caller created the argument and can simply following the normal rules for lifetime.

The implementation continues to treat all async methods the same way to ensure that parameters are passed by value under the expectation that they will be implemented as coroutines.


bool is_async() const
{
if (is_put_overload(m_method))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per the detailed description above, this function's body is optimized for actual usage in a specific case, rather than simply providing an answer to whether the method is async. It would make sense to pick a more specific name and/or add a comment that's a bit more durable. Otherwise it's very non-obvious as to why a property setter is considered "async".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll add some of that explanation as a comment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - added a comment.

@kennykerr kennykerr merged commit 8d849c1 into master Jul 11, 2019
@kennykerr kennykerr deleted the kennkerr-async2 branch July 11, 2019 23:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants