-
Notifications
You must be signed in to change notification settings - Fork 262
Fix ABI conformance of IMap::Remove, add TryRemove #655
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
`single_threaded_map()`'s IMap::Remove did not throw `hresult_out_of_range` on attempts to remove a nonexistent key. Now it throws. Failure to remove a nonexistent key does not invalidate iterators, because nothing actually changed. This brings the map implementation in line with the implementations in other projections. Note that this is a breaking change. Code that assumed nonexistent objects could be harmlessly removed will encounter exceptions when run against C++/WinRT implementations. This was, however, a pre-existing bug, because implementations from other projections (C#, C++/CX) always threw under those conditions. Added a TryRemove() method for people who wanted the nonthrowing version. Note that fixing the ABI conformance is required in order for TryRemove to work, because TryRemove relies on the call to Remove failing if the key doesn't exist. (JavaScript doesn't project objects as maps, so there is nothing to validate there.) Tightened the behavior of TryLookup and TryRemove so they propagate RPC failures. Because the inability to remove the item could be due to the server being unavailable, and that's not the same as the item not existing in the collection. Previous code treated loss of server the same as "The item doesn't exist", which is not true: The item could exist, we just were unable to contact the server to find out.
| auto found = container.find(static_cast<D const&>(*this).wrap_value(key)); | ||
| if (found == container.end()) | ||
| { | ||
| throw hresult_out_of_bounds(); |
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 there a reason why it's important that Remove throws when the key is not found, beyond consistency with other implementations?
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.
It prevents TryRemove from working correctly.
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.
Yes, but it sounds like a circular argument. TryRemove needs Remove to change. TryRemove is needed because Remove has changed. 😉
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.
TryRemove is needed because if the map came from somebody other than C++/WinRT, it will throw. For example, if you want to "TryRemove" from CoreApplication.Properties, you cannot use "Remove" because that property set is implemented in WRL, not C++/WinRT, and it throws on key not found.
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.
Got it - thanks.
|
/azp run |
|
No pipelines are associated with this pull request. |
because they can throw on other errors. Added unit test to verify that errors other than "key not found" are propagated.
|
/azp run |
|
No pipelines are associated with this pull request. |
single_threaded_map()'s IMap::Remove did not throwhresult_out_of_rangeon attempts to remove a nonexistent key. Now it throws.Note that this is a breaking change. Code that assumed nonexistent objects could be harmlessly removed will encounter exceptions when run against C++/WinRT implementations when they hadn't before this change. This was, however, a pre-existing bug, because implementations from other projections (C#, C++/CX, WRL) always throw under those conditions.
Added a TryRemove() method for people who want the nonthrowing version.
Note that fixing the ABI conformance is required in order for TryRemove to return the correct result, because TryRemove relies on the call to Remove failing if the key doesn't exist.
(JavaScript doesn't project objects as maps, so there is nothing to validate there.)
Tightened the behavior of TryLookup and TryRemove so they swallow only "key not found" and propagate other errors. The inability to remove the item could be due to the server being unavailable, or the app accessing the map from the wrong thread, and that's not the same as the item not existing in the collection. Previous code treated these errors the same as "The item doesn't exist", which is not true: The item could exist, we simply don't know since the call never got off the ground.
Failure to remove a nonexistent key no longer invalidates iterators, because nothing actually changed. This brings the map implementation in line with the implementations in C# and WRL. (C++/CX invalidates prematurely. JavaScript never invalidates iterators.)