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

[ASTextNode2] Upgrade lock safety by protecting all ivars (including rarely-changed ones). #918

Merged
merged 2 commits into from
May 19, 2018

Conversation

appleguy
Copy link
Member

Although I don't know of any specific crashes caused by this, I think we should
lock all properties by default. There are also some indications of premature
optimization in keeping lock scope small, where it is actually important to
have transactional integrity, and also where the ASDisplayNode base class is
otherwise going to repeatedly re-lock the object anyway.

I think this will remain pretty efficient, especially with os_unfair_lock enabled.

@appleguy appleguy self-assigned this May 14, 2018
Copy link
Member

@Adlai-Holler Adlai-Holler left a comment

Choose a reason for hiding this comment

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

Very nice work! A few small questions/opps then let's land.



_shadowOpacity = shadowOpacity;

[self setNeedsDisplay];
Copy link
Member

Choose a reason for hiding this comment

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

Great place to use ASLockedSelfCompareAssign!

if (ASLockedSelfCompareAssignCopy(_truncationAttributedText, truncationAttributedText)) {
ASLockScopeSelf();
if (!ASObjectIsEqual(_truncationAttributedText, truncationAttributedText)) {
_truncationAttributedText = [truncationAttributedText copy];
[self _invalidateTruncationText];
Copy link
Member

Choose a reason for hiding this comment

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

Why this change? Is it so that we now call _invalidateTruncationText with the lock held?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, otherwise there is no transactional integrity.

Copy link
Member

Choose a reason for hiding this comment

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

OK in cases such as this (side effect keeps lock), we can use the non-locked compare-assign macros, like so:

ASLockScopeSelf();
if (ASCompareAssignCopy(_truncationAttributedText, truncationATtributedText)) {
  [self _invalidateTruncationText];
}

I set it up to work either way!

Copy link
Member Author

Choose a reason for hiding this comment

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

Great! This is definitely an improvement.

I'm having trouble getting the minutes to circle back to this; will try, maybe this weekend.

@@ -210,6 +212,7 @@ - (BOOL)supportsLayerBacking

- (void)setTextContainerInset:(UIEdgeInsets)textContainerInset
{
ASLockScopeSelf();
BOOL needsUpdate = !UIEdgeInsetsEqualToEdgeInsets(_textContainer.insets, textContainerInset);
_textContainer.insets = textContainerInset;
Copy link
Member

Choose a reason for hiding this comment

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

Good place for ASLockedSelfCompareAssignCustom

// If the text contains any links, return NO.
NSAttributedString *attributedText = self.attributedText;
NSAttributedString *attributedText = _attributedText;
Copy link
Member

Choose a reason for hiding this comment

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

Since we just took the lock, can we go back to using the ivar here?

@Adlai-Holler
Copy link
Member

Just to note: _textContainer is a true invariant of the node and never changes. Its properties are atomic. We should hold the lock when making batch accesses to properties but otherwise it can be accessed without the lock. Its -copy method is also atomic.

…rarely-changed ones).

Although I don't know of any specific crashes caused by this, I think we should
lock all properties by default. There are also some indications of premature
optimization in keeping lock scope small, where it is actually important to
have transactional integrity, and also where the ASDisplayNode base class is
otherwise going to repeatedly re-lock the object anyway.

I think this will remain pretty efficient, especially with os_unfair_lock enabled.
@Adlai-Holler Adlai-Holler force-pushed the ASTextNode2ThreadSafety branch 2 times, most recently from b94c2ba to f7ac965 Compare May 19, 2018 15:49
Copy link
Member

@Adlai-Holler Adlai-Holler left a comment

Choose a reason for hiding this comment

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

I put the finishing touches on it (used the compare-assign macros with the locking fixes). So naturally, I approve! 💯 💯 🔥 😂😂😂

@Adlai-Holler Adlai-Holler merged commit 6799e26 into master May 19, 2018
@Adlai-Holler Adlai-Holler deleted the ASTextNode2ThreadSafety branch May 19, 2018 19:47
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

2 participants