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

Fix ActOnEveryObject missing changes when SuppressChangeNotifications is used #1685

Closed
wants to merge 4 commits into from
Closed

Fix ActOnEveryObject missing changes when SuppressChangeNotifications is used #1685

wants to merge 4 commits into from

Conversation

Wouterdek
Copy link
Contributor

@Wouterdek Wouterdek commented Jul 10, 2018

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix.

What is the current behavior? (You can also link to an open issue here)
Previously ActOnEveryObject() would not handle list changes correctly if the changes were made while SuppressChangeNotifications() was used. This is because SuppressChangeNotifications() currently publishes a reset Changing notification after the changes have been made. See issue #1675.

What is the new behavior (if this is a feature change)?
SuppressChangeNotifications() now publishes the reset Changing notification before the changes are made, when the suppression is first enabled.

What might this PR break?
Protected virtual method publishResetNotification() is removed. It is not used in the class anymore and current subclasses might be overriding it because it affects Reset() and SuppressChangeNotifications(), which it doesn't anymore.

Please check if the PR fulfills these requirements

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

Other information:

vatsalyagoel and others added 2 commits May 12, 2018 14:27
… suppressed

Previously ActOnEveryObject would not handle list changes correctly if the changes were made while SuppressChangeNotifications() was used.
With this commit, ActOnEveryObject works as expected.

Fixes issue #1675.
BREAKING CHANGE: protected virtual method publishResetNotification()  is removed. It is not used anymore and current subclasses might be overriding it because it affects Reset() and SuppressChangeNotifications(), which it doesn't anymore .
@dnfclas
Copy link

dnfclas commented Jul 10, 2018

CLA assistant check
All CLA requirements met.

@glennawatson glennawatson requested review from a team July 10, 2018 11:33
@@ -579,7 +580,10 @@ public IDisposable SuppressChangeNotifications()

return new CompositeDisposable(this.suppressChangeNotifications(), Disposable.Create(() => {
if (Interlocked.Decrement(ref _resetNotificationCount) == 0) {
publishResetNotification();
if (resetEventArgs == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Potentially a threading issue here, since your dispose may not be called in the same thread as when it was created. Probably should use a Interlocked.Exchange or something?

Copy link
Contributor

Choose a reason for hiding this comment

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

It might be alright given that it's inside the Interlocked.Decrement() though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As resetEventArgs is set (if it is set) before the disposable is returned, and nothing can change its value until the disposable is called, I don't really see how a race condition could occur? Duplicate/missing changed notifications cannot occur since Interlocked.Decrement is still used. Am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I agree, was just a initial reaction until I saw everything inside the Decrement statement.

@glennawatson glennawatson requested a review from a team July 10, 2018 23:38
@@ -481,6 +481,64 @@ public void GetAResetWhenWeAddALotOfItems()
Assert.Equal(1, reset.Count);
}

[Fact]
public void ActOnEveryObjectShouldHandleAddRemoveAndClear()
Copy link
Member

Choose a reason for hiding this comment

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

I think from a clarity point of view, this test is doing too much, I think each separate case of ActOnEvery… should be a separate test.

}

[Fact]
public void ActOnEveryObjectShouldNotMissChangesUnderSuppressedNotifications()
Copy link
Member

Choose a reason for hiding this comment

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

Likewise, I think this would be clearer as a couple of tests


if (Interlocked.Increment(ref _resetNotificationCount) == 1) {
// Changes were not suppressed before, publish a Changing reset notification.
resetEventArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason to not use the reset/publishResetNotification in here? Wondering if we can reduce the breaking changes to a minimum.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that with this patch only a Changed, but no Changing notification, is pushed in the disposable. Using publishResetNotification() in here would cause a duplicate Changing notification after the changes have been made, which would be unexpected but perhaps less breaking. I removed publishResetNotification() because it was used only in Reset() and SuppressChangeNotifications() and since it is no longer used there I feel like it would be better to have a compiler error rather than unexpected behaviour when overriding this method.

I guess it comes down to this: Do you prefer a duplicate, technically incorrect, Changing notification but no breaking changes? Or would you rather have the (small) breaking change and no duplicate notifications?

@olevett
Copy link
Member

olevett commented Jul 12, 2018

Only just spotted, can we change this PR to be against master rather than develop?

@Wouterdek Wouterdek changed the base branch from develop to master July 12, 2018 13:29
@glennawatson
Copy link
Contributor

That merge we definitely don't want. Now we got mass number of changes. You probably want to do some sort of rebase operation. Another option is close this pr, then you just cherry pick the commits into a new branch from master your changes and submit a new pr.

@Wouterdek
Copy link
Contributor Author

I'll close this one, and open a cherry-picked new one later.

Also, not sure if you always want your PRs against master, but if so you might want to update the guidelines.

@Wouterdek Wouterdek closed this Jul 12, 2018
@glennawatson
Copy link
Contributor

Good point. I will do a pr for that later today. It was something that changed with the RxUI 8 release.

@Wouterdek Wouterdek deleted the fix-act-on-every-object branch July 12, 2018 14:30
@lock lock bot locked and limited conversation to collaborators Jun 25, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants