diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
index 717a8304..1d117a77 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
@@ -34,11 +34,11 @@
Json.NET
- HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_IMMUTABLE_COLLECTIONS;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;$(AdditionalConstants)
+ HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_IMMUTABLE_COLLECTIONS;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;$(AdditionalConstants)
Json.NET .NET 4.0
- NET40;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;$(AdditionalConstants)
+ NET40;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;$(AdditionalConstants)
Json.NET .NET 3.5
@@ -63,7 +63,7 @@
Json.NET .NET Standard 1.3
- NETSTANDARD1_3;PORTABLE;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DYNAMIC;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_IMMUTABLE_COLLECTIONS;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_ISET;HAVE_LINQ;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_BINDER;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;HAVE_XML_DOCUMENT;$(AdditionalConstants)
+ NETSTANDARD1_3;PORTABLE;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DYNAMIC;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_IMMUTABLE_COLLECTIONS;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_ISET;HAVE_LINQ;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_BINDER;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;HAVE_XML_DOCUMENT;HAVE_CONCURRENT_DICTIONARY;$(AdditionalConstants)
Json.NET Portable .NET 4.0
diff --git a/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs b/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
index d093f622..324d08b1 100644
--- a/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
+++ b/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
@@ -24,6 +24,9 @@
#endregion
using System;
+#if HAVE_CONCURRENT_DICTIONARY
+using System.Collections.Concurrent;
+#endif
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json.Utilities;
@@ -69,7 +72,7 @@ namespace Newtonsoft.Json.Serialization
{
private static readonly object TypeContractCacheLock = new object();
private static readonly PropertyNameTable NameTable = new PropertyNameTable();
- private static Dictionary _contractCache;
+ private static readonly ConcurrentDictionary _contractCache = new ConcurrentDictionary();
///
/// Initializes a new instance of the class.
@@ -96,27 +99,8 @@ namespace Newtonsoft.Json.Serialization
}
// for backwards compadibility the CamelCasePropertyNamesContractResolver shares contracts between instances
- JsonContract contract;
ResolverContractKey key = new ResolverContractKey(GetType(), type);
- Dictionary cache = _contractCache;
- if (cache == null || !cache.TryGetValue(key, out contract))
- {
- contract = CreateContract(type);
-
- // avoid the possibility of modifying the cache dictionary while another thread is accessing it
- lock (TypeContractCacheLock)
- {
- cache = _contractCache;
- Dictionary updatedCache = (cache != null)
- ? new Dictionary(cache)
- : new Dictionary();
- updatedCache[key] = contract;
-
- _contractCache = updatedCache;
- }
- }
-
- return contract;
+ return _contractCache.GetOrAdd(key, k => CreateContract(type));
}
internal override PropertyNameTable GetNameTable()
diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
index d5e840f3..575ed346 100644
--- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
+++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
@@ -25,6 +25,9 @@
using System;
using System.Collections;
+#if HAVE_CONCURRENT_DICTIONARY
+using System.Collections.Concurrent;
+#endif
using Newtonsoft.Json.Schema;
using System.Collections.Generic;
using System.ComponentModel;
@@ -47,6 +50,7 @@ using Newtonsoft.Json.Utilities.LinqBridge;
using System.Linq;
#endif
+using Newtonsoft.Json.Serialization;
namespace Newtonsoft.Json.Serialization
{
@@ -92,7 +96,7 @@ namespace Newtonsoft.Json.Serialization
private readonly object _typeContractCacheLock = new object();
private readonly PropertyNameTable _nameTable = new PropertyNameTable();
- private Dictionary _contractCache;
+ private readonly ConcurrentDictionary _contractCache = new ConcurrentDictionary();
///
/// Gets a value indicating whether members are being get and set using dynamic code generation.
@@ -175,26 +179,7 @@ namespace Newtonsoft.Json.Serialization
throw new ArgumentNullException(nameof(type));
}
- JsonContract contract;
- Dictionary cache = _contractCache;
- if (cache == null || !cache.TryGetValue(type, out contract))
- {
- contract = CreateContract(type);
-
- // avoid the possibility of modifying the cache dictionary while another thread is accessing it
- lock (_typeContractCacheLock)
- {
- cache = _contractCache;
- Dictionary updatedCache = (cache != null)
- ? new Dictionary(cache)
- : new Dictionary();
- updatedCache[type] = contract;
-
- _contractCache = updatedCache;
- }
- }
-
- return contract;
+ return _contractCache.GetOrAdd(type, CreateContract);
}
///
diff --git a/Src/Newtonsoft.Json/Utilities/ConcurrentDictionary.cs b/Src/Newtonsoft.Json/Utilities/ConcurrentDictionary.cs
new file mode 100644
index 00000000..be1b89a8
--- /dev/null
+++ b/Src/Newtonsoft.Json/Utilities/ConcurrentDictionary.cs
@@ -0,0 +1,76 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !HAVE_CONCURRENT_DICTIONARY
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Newtonsoft.Json.Serialization
+{
+ internal sealed class ConcurrentDictionary
+ {
+ private readonly object _lock = new object();
+ private Dictionary _dictionary = new Dictionary();
+
+ public TValue GetOrAdd(TKey key, Func valueFactory)
+ {
+ TValue value;
+ if (!_dictionary.TryGetValue(key, out value))
+ {
+ return AddValue(key, valueFactory);
+ }
+
+ return value;
+ }
+
+ private TValue AddValue(TKey key, Func valueFactory)
+ {
+ TValue value = valueFactory(key);
+
+ lock (_lock)
+ {
+ // double check locking
+ TValue checkValue;
+ if (_dictionary.TryGetValue(key, out checkValue))
+ {
+ return checkValue;
+ }
+
+ Dictionary newDictionary = new Dictionary(_dictionary);
+ newDictionary[key] = value;
+
+#if HAVE_MEMORY_BARRIER
+ Thread.MemoryBarrier();
+#endif
+ _dictionary = newDictionary;
+ }
+
+ return value;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Utilities/ThreadSafeStore.cs b/Src/Newtonsoft.Json/Utilities/ThreadSafeStore.cs
index 89a94dc8..0ab83dcf 100644
--- a/Src/Newtonsoft.Json/Utilities/ThreadSafeStore.cs
+++ b/Src/Newtonsoft.Json/Utilities/ThreadSafeStore.cs
@@ -24,19 +24,16 @@
#endregion
using System;
-using System.Collections.Generic;
-#if !HAVE_LINQ
-using Newtonsoft.Json.Utilities.LinqBridge;
+#if HAVE_CONCURRENT_DICTIONARY
+using System.Collections.Concurrent;
#endif
-using System.Threading;
using Newtonsoft.Json.Serialization;
namespace Newtonsoft.Json.Utilities
{
internal class ThreadSafeStore
{
- private readonly object _lock = new object();
- private Dictionary _store;
+ private readonly ConcurrentDictionary _store;
private readonly Func _creator;
public ThreadSafeStore(Func creator)
@@ -47,51 +44,12 @@ namespace Newtonsoft.Json.Utilities
}
_creator = creator;
- _store = new Dictionary();
+ _store = new ConcurrentDictionary();
}
public TValue Get(TKey key)
{
- TValue value;
- if (!_store.TryGetValue(key, out value))
- {
- return AddValue(key);
- }
-
- return value;
- }
-
- private TValue AddValue(TKey key)
- {
- TValue value = _creator(key);
-
- lock (_lock)
- {
- if (_store == null)
- {
- _store = new Dictionary();
- _store[key] = value;
- }
- else
- {
- // double check locking
- TValue checkValue;
- if (_store.TryGetValue(key, out checkValue))
- {
- return checkValue;
- }
-
- Dictionary newStore = new Dictionary(_store);
- newStore[key] = value;
-
-#if HAVE_MEMORY_BARRIER
- Thread.MemoryBarrier();
-#endif
- _store = newStore;
- }
-
- return value;
- }
+ return _store.GetOrAdd(key, _creator);
}
}
}
\ No newline at end of file