Skip to content

Conversation

cconstantin
Copy link
Contributor

Use ConcurrentDictionary.GetOrAdd instead of TryGet + AddOrUpdate

@cconstantin cconstantin changed the title Fix 1522 Ensure extensions and persistence plugins are only registered/created once Fix #1522 Ensure extensions and persistence plugins are only registered/created once Jan 15, 2016
@Aaronontheweb
Copy link
Member

@Horusiath @Zetanova care to comment on this, Akka.Persistence gurus?

@Zetanova
Copy link
Contributor

The combination of AtomicReference TrySet+CompareAndSet(of IImmutableMap)+Get should be thread safe. If there is a race condition then it is to be in likly ImmutableTreeMap or unlikly in AtomicReferenece

Maybe fix for ImmutableTreeMap:
#1645

Maybe Fix for AttomicReference:
#1615

@cconstantin
Copy link
Contributor Author

I have a test that's calling SnapshotFor in two threads concurrently. Fails on dev, passes with the fix. I'll find an appropriate location for it and push it up.

On Fri, Jan 15, 2016 at 7:58 PM -0800, "Zetanova" notifications@github.com wrote:

The combination of AtomicReference TrySet+CompareAndSet(of IImmutableMap)+Get should be thread safe. If there is a race condition then it is likly to be in likly ImmutableTreeMap or unlikly in AtomicReferenece

Maybe fix for ImmutableTreeMap:

#1645

Maybe Fix for AttomicReference:

#1615


Reply to this email directly or view it on GitHub.

if(!_extensions.ContainsKey(extension.ExtensionType))
{
_extensions.TryAdd(extension.ExtensionType, new Lazy<object>(() => extension.CreateExtension(this)));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This part was the cause for race conditions in the old code.
there is a check if something does not exist, and if so, it adds an extension.. classic race condition semantics.

The new code fixes that.

Copy link
Contributor

Choose a reason for hiding this comment

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

this can be the couse. Should that "return extension.Get(this);" not actualy using the result of _extensions.GetOrAdd ?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, it could just do a return on that call.

@rogeralsing
Copy link
Contributor

The problems in the old code does not relate to atomic references or immutable lists, it comes down to standard race conditions...

IF something THEN  //this 
    DOSTUFF        //is racy...

The fixes looks good to me.

Aaronontheweb added a commit that referenced this pull request Jan 18, 2016
Fix #1522 Ensure extensions and persistence plugins are only registered/created once
@Aaronontheweb Aaronontheweb merged commit 2da2a88 into akkadotnet:dev Jan 18, 2016
@Aaronontheweb
Copy link
Member

I reviewed this also and agreed with @rogeralsing - better to use a ConcurrentDictionary here.

@Aaronontheweb
Copy link
Member

Just for reference, in @Horusiath's original PR he talked about some of the potential trade-offs of switching to ConcurrentDictionary. Putting this here just in case merging this code comes back to bite us in the ass :p

#1543

@cconstantin cconstantin deleted the fix-1522 branch March 10, 2016 15:53
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.

5 participants