Skip to content

Commit be7c7f9

Browse files
committedNov 10, 2011
Replaced all locks with a faster lock-free Reference Swap/CompareExchange implementation
1 parent 574167e commit be7c7f9

28 files changed

+594
-538
lines changed
 

‎NuGet/lib/net35/ServiceStack.Text.dll

512 Bytes
Binary file not shown.

‎lib/tests/ServiceStack.Common.dll

1 KB
Binary file not shown.

‎lib/tests/ServiceStack.Common.pdb

258 KB
Binary file not shown.

‎lib/tests/ServiceStack.Interfaces.dll

1 KB
Binary file not shown.
Binary file not shown.

‎lib/tests/ServiceStack.OrmLite.dll

43.5 KB
Binary file not shown.
41 KB
Binary file not shown.

‎lib/tests/ServiceStack.Text.dll

0 Bytes
Binary file not shown.

‎lib/tests/ServiceStack.dll

410 KB
Binary file not shown.

‎src/ServiceStack.Text/Common/DeserializeArray.cs

+34-26
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,37 @@
1313
using System;
1414
using System.Collections.Generic;
1515
using System.Reflection;
16+
using System.Threading;
1617

1718
namespace ServiceStack.Text.Common
1819
{
1920
internal static class DeserializeArrayWithElements<TSerializer>
2021
where TSerializer : ITypeSerializer
2122
{
22-
private static readonly Dictionary<Type, ParseArrayOfElementsDelegate> ParseDelegateCache
23+
private static Dictionary<Type, ParseArrayOfElementsDelegate> ParseDelegateCache
2324
= new Dictionary<Type, ParseArrayOfElementsDelegate>();
2425

2526
private delegate object ParseArrayOfElementsDelegate(string value, ParseStringDelegate parseFn);
2627

2728
public static Func<string, ParseStringDelegate, object> GetParseFn(Type type)
2829
{
2930
ParseArrayOfElementsDelegate parseFn;
30-
if (!ParseDelegateCache.TryGetValue(type, out parseFn))
31-
{
32-
var genericType = typeof(DeserializeArrayWithElements<,>)
33-
.MakeGenericType(type, typeof(TSerializer));
31+
if (ParseDelegateCache.TryGetValue(type, out parseFn)) return parseFn.Invoke;
3432

35-
var mi = genericType.GetMethod("ParseGenericArray",
36-
BindingFlags.Public | BindingFlags.Static);
33+
var genericType = typeof(DeserializeArrayWithElements<,>).MakeGenericType(type, typeof(TSerializer));
34+
var mi = genericType.GetMethod("ParseGenericArray", BindingFlags.Public | BindingFlags.Static);
35+
parseFn = (ParseArrayOfElementsDelegate)Delegate.CreateDelegate(typeof(ParseArrayOfElementsDelegate), mi);
36+
37+
Dictionary<Type, ParseArrayOfElementsDelegate> snapshot, newCache;
38+
do
39+
{
40+
snapshot = ParseDelegateCache;
41+
newCache = new Dictionary<Type, ParseArrayOfElementsDelegate>(ParseDelegateCache);
42+
newCache[type] = parseFn;
43+
44+
} while (!ReferenceEquals(
45+
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
3746

38-
parseFn = (ParseArrayOfElementsDelegate)Delegate.CreateDelegate(typeof(ParseArrayOfElementsDelegate), mi);
39-
ParseDelegateCache[type] = parseFn;
40-
}
4147
return parseFn.Invoke;
4248
}
4349
}
@@ -90,26 +96,28 @@ public static T[] ParseGenericArray(string value, ParseStringDelegate elementPar
9096
internal static class DeserializeArray<TSerializer>
9197
where TSerializer : ITypeSerializer
9298
{
93-
private static readonly Dictionary<Type, ParseStringDelegate> ParseDelegateCache
94-
= new Dictionary<Type, ParseStringDelegate>();
99+
private static Dictionary<Type, ParseStringDelegate> ParseDelegateCache = new Dictionary<Type, ParseStringDelegate>();
95100

96101
public static ParseStringDelegate GetParseFn(Type type)
97102
{
98103
ParseStringDelegate parseFn;
99-
if (!ParseDelegateCache.TryGetValue(type, out parseFn))
100-
{
101-
var genericType = typeof(DeserializeArray<,>)
102-
.MakeGenericType(type, typeof(TSerializer));
103-
104-
var mi = genericType.GetMethod("GetParseFn",
105-
BindingFlags.Public | BindingFlags.Static);
106-
107-
var parseFactoryFn = (Func<ParseStringDelegate>)Delegate.CreateDelegate(
108-
typeof(Func<ParseStringDelegate>), mi);
109-
110-
parseFn = parseFactoryFn();
111-
ParseDelegateCache[type] = parseFn;
112-
}
104+
if (ParseDelegateCache.TryGetValue(type, out parseFn)) return parseFn;
105+
106+
var genericType = typeof(DeserializeArray<,>).MakeGenericType(type, typeof(TSerializer));
107+
var mi = genericType.GetMethod("GetParseFn", BindingFlags.Public | BindingFlags.Static);
108+
var parseFactoryFn = (Func<ParseStringDelegate>)Delegate.CreateDelegate(
109+
typeof(Func<ParseStringDelegate>), mi);
110+
parseFn = parseFactoryFn();
111+
112+
Dictionary<Type, ParseStringDelegate> snapshot, newCache;
113+
do
114+
{
115+
snapshot = ParseDelegateCache;
116+
newCache = new Dictionary<Type, ParseStringDelegate>(ParseDelegateCache);
117+
newCache[type] = parseFn;
118+
119+
} while (!ReferenceEquals(
120+
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
113121

114122
return parseFn;
115123
}

‎src/ServiceStack.Text/Common/DeserializeCollection.cs

+20-13
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using System;
1414
using System.Collections.Generic;
1515
using System.Reflection;
16+
using System.Threading;
1617

1718
namespace ServiceStack.Text.Common
1819
{
@@ -88,26 +89,32 @@ private static ICollection<T> CreateAndPopulate<T>(Type ofCollectionType, T[] wi
8889
return collection;
8990
}
9091

91-
private static readonly Dictionary<Type, ParseCollectionDelegate> ParseDelegateCache
92+
private static Dictionary<Type, ParseCollectionDelegate> ParseDelegateCache
9293
= new Dictionary<Type, ParseCollectionDelegate>();
9394

9495
private delegate object ParseCollectionDelegate(string value, Type createType, ParseStringDelegate parseFn);
9596

9697
public static object ParseCollectionType(string value, Type createType, Type elementType, ParseStringDelegate parseFn)
9798
{
98-
var mi = typeof(DeserializeCollection<TSerializer>)
99-
.GetMethod("ParseCollection", BindingFlags.Static | BindingFlags.Public);
100-
10199
ParseCollectionDelegate parseDelegate;
102-
103-
if (!ParseDelegateCache.TryGetValue(elementType, out parseDelegate))
104-
{
105-
var genericMi = mi.MakeGenericMethod(new[] { elementType });
106-
parseDelegate = (ParseCollectionDelegate) Delegate.CreateDelegate(typeof(ParseCollectionDelegate), genericMi);
107-
ParseDelegateCache[elementType] = parseDelegate;
108-
}
109-
110-
return parseDelegate(value, createType, parseFn);
100+
if (ParseDelegateCache.TryGetValue(elementType, out parseDelegate))
101+
return parseDelegate(value, createType, parseFn);
102+
103+
var mi = typeof(DeserializeCollection<TSerializer>).GetMethod("ParseCollection", BindingFlags.Static | BindingFlags.Public);
104+
var genericMi = mi.MakeGenericMethod(new[] { elementType });
105+
parseDelegate = (ParseCollectionDelegate)Delegate.CreateDelegate(typeof(ParseCollectionDelegate), genericMi);
106+
107+
Dictionary<Type, ParseCollectionDelegate> snapshot, newCache;
108+
do
109+
{
110+
snapshot = ParseDelegateCache;
111+
newCache = new Dictionary<Type, ParseCollectionDelegate>(ParseDelegateCache);
112+
newCache[elementType] = parseDelegate;
113+
114+
} while (!ReferenceEquals(
115+
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
116+
117+
return parseDelegate(value, createType, parseFn);
111118
}
112119
}
113120
}

‎src/ServiceStack.Text/Common/DeserializeDictionary.cs

+18-11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System.Reflection;
1616
using System.Runtime.Serialization;
1717
using System.Text;
18+
using System.Threading;
1819
using ServiceStack.Text.Json;
1920

2021
namespace ServiceStack.Text.Common
@@ -145,7 +146,7 @@ private static int VerifyAndGetStartIndex(string value, Type createMapType)
145146
return index;
146147
}
147148

148-
private static readonly Dictionary<string, ParseDictionaryDelegate> ParseDelegateCache
149+
private static Dictionary<string, ParseDictionaryDelegate> ParseDelegateCache
149150
= new Dictionary<string, ParseDictionaryDelegate>();
150151

151152
private delegate object ParseDictionaryDelegate(string value, Type createMapType,
@@ -154,19 +155,25 @@ private delegate object ParseDictionaryDelegate(string value, Type createMapType
154155
public static object ParseDictionaryType(string value, Type createMapType, Type[] argTypes,
155156
ParseStringDelegate keyParseFn, ParseStringDelegate valueParseFn)
156157
{
157-
var mi = typeof(DeserializeDictionary<TSerializer>)
158-
.GetMethod("ParseDictionary", BindingFlags.Static | BindingFlags.Public);
159158

160159
ParseDictionaryDelegate parseDelegate;
161160
var key = GetTypesKey(argTypes);
162-
if (!ParseDelegateCache.TryGetValue(key, out parseDelegate))
163-
{
164-
var genericMi = mi.MakeGenericMethod(argTypes);
165-
parseDelegate = (ParseDictionaryDelegate)Delegate.CreateDelegate(
166-
typeof(ParseDictionaryDelegate), genericMi);
167-
168-
ParseDelegateCache[key] = parseDelegate;
169-
}
161+
if (ParseDelegateCache.TryGetValue(key, out parseDelegate))
162+
return parseDelegate(value, createMapType, keyParseFn, valueParseFn);
163+
164+
var mi = typeof(DeserializeDictionary<TSerializer>).GetMethod("ParseDictionary", BindingFlags.Static | BindingFlags.Public);
165+
var genericMi = mi.MakeGenericMethod(argTypes);
166+
parseDelegate = (ParseDictionaryDelegate)Delegate.CreateDelegate(typeof(ParseDictionaryDelegate), genericMi);
167+
168+
Dictionary<string, ParseDictionaryDelegate> snapshot, newCache;
169+
do
170+
{
171+
snapshot = ParseDelegateCache;
172+
newCache = new Dictionary<string, ParseDictionaryDelegate>(ParseDelegateCache);
173+
newCache[key] = parseDelegate;
174+
175+
} while (!ReferenceEquals(
176+
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
170177

171178
return parseDelegate(value, createMapType, keyParseFn, valueParseFn);
172179
}

‎src/ServiceStack.Text/Common/DeserializeListWithElements.cs

+20-16
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using System.Collections.Generic;
1515
using System.Collections.ObjectModel;
1616
using System.Reflection;
17+
using System.Threading;
1718

1819
namespace ServiceStack.Text.Common
1920
{
@@ -22,28 +23,31 @@ internal static class DeserializeListWithElements<TSerializer>
2223
{
2324
internal static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
2425

25-
private static readonly Dictionary<Type, ParseListDelegate> ParseDelegateCache
26+
private static Dictionary<Type, ParseListDelegate> ParseDelegateCache
2627
= new Dictionary<Type, ParseListDelegate>();
2728

2829
private delegate object ParseListDelegate(string value, Type createListType, ParseStringDelegate parseFn);
2930

3031
public static Func<string, Type, ParseStringDelegate, object> GetListTypeParseFn(
31-
Type createListType, Type elementType,
32-
ParseStringDelegate parseFn)
32+
Type createListType, Type elementType, ParseStringDelegate parseFn)
3333
{
3434
ParseListDelegate parseDelegate;
35-
if (!ParseDelegateCache.TryGetValue(elementType, out parseDelegate))
36-
{
37-
var genericType = typeof(DeserializeListWithElements<,>)
38-
.MakeGenericType(elementType, typeof(TSerializer));
35+
if (ParseDelegateCache.TryGetValue(elementType, out parseDelegate))
36+
return parseDelegate.Invoke;
3937

40-
var mi = genericType.GetMethod("ParseGenericList",
41-
BindingFlags.Static | BindingFlags.Public);
38+
var genericType = typeof(DeserializeListWithElements<,>).MakeGenericType(elementType, typeof(TSerializer));
39+
var mi = genericType.GetMethod("ParseGenericList", BindingFlags.Static | BindingFlags.Public);
40+
parseDelegate = (ParseListDelegate)Delegate.CreateDelegate(typeof(ParseListDelegate), mi);
4241

43-
parseDelegate = (ParseListDelegate)Delegate.CreateDelegate(typeof(ParseListDelegate), mi);
42+
Dictionary<Type, ParseListDelegate> snapshot, newCache;
43+
do
44+
{
45+
snapshot = ParseDelegateCache;
46+
newCache = new Dictionary<Type, ParseListDelegate>(ParseDelegateCache);
47+
newCache[elementType] = parseDelegate;
4448

45-
ParseDelegateCache[elementType] = parseDelegate;
46-
}
49+
} while (!ReferenceEquals(
50+
Interlocked.CompareExchange(ref ParseDelegateCache, newCache, snapshot), snapshot));
4751

4852
return parseDelegate.Invoke;
4953
}
@@ -104,12 +108,12 @@ public static IList<T> ParseGenericList(string value, Type createListType, Parse
104108
{
105109
if ((value = DeserializeListWithElements<TSerializer>.StripList(value)) == null) return null;
106110

107-
bool isReadOnly = null == createListType ? false
108-
: createListType.IsGenericType && createListType.GetGenericTypeDefinition() == typeof(ReadOnlyCollection<>);
111+
var isReadOnly = createListType != null
112+
&& (createListType.IsGenericType && createListType.GetGenericTypeDefinition() == typeof(ReadOnlyCollection<>));
109113

110114
var to = (createListType == null || isReadOnly)
111-
? new List<T>()
112-
: (IList<T>)ReflectionExtensions.CreateInstance(createListType);
115+
? new List<T>()
116+
: (IList<T>)ReflectionExtensions.CreateInstance(createListType);
113117

114118
if (value == string.Empty) return to;
115119

‎src/ServiceStack.Text/Common/JsDelegates.cs

+2
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ namespace ServiceStack.Text.Common
3131
public delegate object ParseStringDelegate(string stringValue);
3232

3333
public delegate object ConvertObjectDelegate(object fromObject);
34+
35+
public delegate object ConvertInstanceDelegate(object obj, Type type);
3436
}

0 commit comments

Comments
 (0)
Please sign in to comment.