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

Mark ASRunLoopQueue as drained if it contains only NULLs #558

Merged
merged 7 commits into from
Sep 11, 2017

Conversation

cesteban
Copy link
Contributor

@cesteban cesteban commented Sep 9, 2017

I wrote a failing tests for #518. Then made it pass.

Apparently, the problem is NSPointerArray won't be marked as needsCompaction when stored weak pointers become NULL. This makes subsequent calls to compact to return early without effectively removing NULL's. As a result ASRunLoopQueue is never marked as drained, event though there is no more work to do.

I added an isEmpty public property to ASRunLoopQueue which is only used in tests. That's not pretty, but I went this way because IMO the property makes sense in an API like that (if you have a queue, it's very natural to have a way to know if it's empty). If you don't want to have this property, we need to find out another way for the test to sense that the queue has been marked as drained.

Finally, I believe ASRunLoopQueue should have a lot more tests, given the importance of the component. I would try to find the time to write a bunch of them, but that should be a different branch IMO.

Please, let me know your thoughts.

Edit (huy): Closes #518.

@maicki maicki requested review from Adlai-Holler and removed request for Adlai-Holler September 9, 2017 20:18
@cesteban
Copy link
Contributor Author

cesteban commented Sep 10, 2017

I finally covered ASRunLoopQueue with tests.

Copy link
Member

@nguyenhuy nguyenhuy left a comment

Choose a reason for hiding this comment

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

First of all, thanks for investigating the problem and submit this patch! Extra kudos for the new unit tests!

That being said, I have 1 small problem with the new _isQueueDrained state, that is we need to do extra work to make sure it's up-to-date. If the problem lies within NSPointerArray (and there is indeed a radar for it), maybe we should somehow force it to do the right thing? I think there are a couple of things we can do:

  • Use allObjects.count instead of count. Unlike the latter, the former API shouldn't include NULL pointers.
  • Whenever needed, force the pointer array to compact by inserting a nil pointer before calling compact, as suggested here.

Let me know what you think!

CHANGELOG.md Outdated
@@ -20,6 +20,7 @@
- Fixed a memory corruption issue in the ASImageNode display system. [Adlai Holler](https://github.com/Adlai-Holler) [#555](https://github.com/TextureGroup/Texture/pull/555)
- [Breaking] Rename ASCollectionGalleryLayoutSizeProviding to ASCollectionGalleryLayoutPropertiesProviding. Besides a fixed item size, it now can provide interitem and line spacings, as well as section inset [Huy Nguyen](https://github.com/nguyenhuy) [#496](https://github.com/TextureGroup/Texture/pull/496) [#533](https://github.com/TextureGroup/Texture/pull/533)
- Deprecate `-[ASDisplayNode displayWillStart]` in favor of `-displayWillStartAsynchronously:` [Huy Nguyen](https://github.com/nguyenhuy) [536](https://github.com/TextureGroup/Texture/pull/536)
- Mark ASRunLoopQueue as drained if it contains only NULLs [Cesar Estebanez](https://github.com/cesteban)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Please add the PR's URL.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, sorry!

@nguyenhuy
Copy link
Member

nguyenhuy commented Sep 11, 2017

Also, please update the license in ASRunLoopQueueTests.m as suggested by Danger above.

@cesteban
Copy link
Contributor Author

@nguyenhuy Actually, my first implementation that passed the test was something similar to this:

    NSInteger foundItemCount = 0;
    for (NSInteger i = 0; i < internalQueueCount && foundItemCount < maxCountToProcess; i++) {
      //...
    }

    if (foundItemCount == 0) {
      // If _internalQueue holds weak references, and all of them just become nil, then the array
      // is never marked as needsCompletion, and compact will return early, not removing the nils.
      // Inserting a nil here ensures the compaction will take place.
      [_internalQueue addPointer:nil];
    }

    [_internalQueue compact];
    if (_internalQueue.count == 0) {
      isQueueDrained = YES;
    }

Do you prefer this kind of approach? I can recover it, just let me know.

@nguyenhuy
Copy link
Member

@cesteban Yes, I think it's a cleaner approach. May worth adding the StackOverflow and OpenRadar links.

@cesteban
Copy link
Contributor Author

Thanks @nguyenhuy. There we go!

Copy link
Member

@nguyenhuy nguyenhuy left a comment

Choose a reason for hiding this comment

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

Great win! Thank you!

@garrettmoon garrettmoon merged commit 002c2d6 into TextureGroup:master Sep 11, 2017
bernieperez pushed a commit to AtomTickets/Texture that referenced this pull request Apr 25, 2018
…p#558)

* Mark ASRunLoopQueue as drained if it contains only NULLs

* Update CHANGELOG.md

* Cover ASRunLoopQueue with tests

* Include PR link in CHANGELOG.md

* Replace license header of ASRunLoopQueueTests.m with correct one

* Insert a nil in _internalQueue to ensure compaction, instead of maintaining a state for _isQueueDrained
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.

None yet

4 participants