-
Notifications
You must be signed in to change notification settings - Fork 55
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
BROOKLYN-245: improve synchronization in entity #96
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1484,15 +1484,21 @@ public void unsubscribeAll() { | |
} | ||
|
||
protected SubscriptionContext getSubscriptionContext() { | ||
synchronized (AbstractEntity.this) { | ||
return getManagementSupport().getSubscriptionContext(); | ||
} | ||
// Rely on synchronization in EntityManagementSupport; synchronizing on AbstractEntity.this | ||
// is dangerous because user's entity code might synchronize on that and call getAttribute. | ||
// Given that getSubscriptionContext is called by AttributeMap.update (via emitInternal), | ||
// that risks deadlock! | ||
return getManagementSupport().getSubscriptionContext(); | ||
} | ||
|
||
protected SubscriptionTracker getSubscriptionTracker() { | ||
// TODO Would be nice to simplify concurrent model, and not synchronize on | ||
// AbstractEntity.this; perhaps could get rid of lazy-initialisation, but then | ||
// would need to first ensure `managementSupport` is definitely initialised. | ||
SubscriptionContext subscriptionContext = getSubscriptionContext(); | ||
synchronized (AbstractEntity.this) { | ||
if (_subscriptionTracker == null) { | ||
_subscriptionTracker = new SubscriptionTracker(getSubscriptionContext()); | ||
_subscriptionTracker = new SubscriptionTracker(subscriptionContext); | ||
} | ||
return _subscriptionTracker; | ||
} | ||
|
@@ -1548,7 +1554,7 @@ public boolean unsubscribe(Entity producer, SubscriptionHandle handle) { | |
* @deprecated since 0.9.0; for internal use only | ||
*/ | ||
@Deprecated | ||
protected synchronized SubscriptionTracker getSubscriptionTracker() { | ||
protected SubscriptionTracker getSubscriptionTracker() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the in contrast to the change to unsynchronize feels like line 1498 could double-check the tracker, and load the
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this existing code is ok, in terms of the deadlock encountered in BROOKLYN-245. The In terms of calling It would be good to remove the As an aside, note that double-checked locking is broken if the field is not declared volatile. Given that, are you ok leaving the code as-is in this PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added another commit that does the I didn't bother with double-checked locking and volatile field. If we care hugely about performance here, then we should instantiate it on entity initialisation (before this method is called), and get rid of all the synchronization in the method. That would be a simpler concurrency model. But it's a bit fiddly because of the use |
||
return subscriptions().getSubscriptionTracker(); | ||
} | ||
|
||
|
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.
fix looks good, agree
EMS
handles synching is sufficient and means we should not try to do so here