Skip to content

Commit 758fcdb

Browse files
committed
Replace Hashtables with generic ConcurrentDictionaries
1 parent 506a1c8 commit 758fcdb

File tree

2 files changed

+54
-89
lines changed

2 files changed

+54
-89
lines changed

Src/Microsoft.Dynamic/ComInterop/ComTypeDesc.cs

Lines changed: 43 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,19 @@
55
#if FEATURE_COM
66

77
using System;
8-
using System.Collections;
8+
using System.Collections.Concurrent;
99
using System.Collections.Generic;
10+
using System.Globalization;
1011
using System.Runtime.InteropServices.ComTypes;
1112
using System.Threading;
1213

1314
namespace Microsoft.Scripting.ComInterop {
1415

1516
public class ComTypeDesc : ComTypeLibMemberDesc {
16-
private string _typeName;
17-
private string _documentation;
18-
//Hashtable is threadsafe for multiple readers single writer.
19-
//Enumerating and writing is mutually exclusive so require locking.
20-
private Hashtable _funcs;
21-
private Hashtable _puts;
22-
private Hashtable _putRefs;
17+
private readonly string _typeName;
18+
private readonly string _documentation;
2319
private ComMethodDesc _getItem;
2420
private ComMethodDesc _setItem;
25-
private Dictionary<string, ComEventDesc> _events;
2621
private static readonly Dictionary<string, ComEventDesc> _EmptyEventsDict = new Dictionary<string, ComEventDesc>();
2722

2823
internal ComTypeDesc(ITypeInfo typeInfo, ComType memberType, ComTypeLibDesc typeLibDesc) : base(memberType) {
@@ -51,122 +46,101 @@ internal static ComTypeDesc FromITypeInfo(ITypeInfo typeInfo, TYPEATTR typeAttr)
5146

5247
internal static ComTypeDesc CreateEmptyTypeDesc() {
5348
ComTypeDesc typeDesc = new ComTypeDesc(null, ComType.Interface, null);
54-
typeDesc._funcs = new Hashtable();
55-
typeDesc._puts = new Hashtable();
56-
typeDesc._putRefs = new Hashtable();
57-
typeDesc._events = _EmptyEventsDict;
49+
typeDesc.Funcs = new ConcurrentDictionary<string, ComMethodDesc>();
50+
typeDesc.Puts = new ConcurrentDictionary<string, ComMethodDesc>();
51+
typeDesc.PutRefs = new ConcurrentDictionary<string, ComMethodDesc>();
52+
typeDesc.Events = _EmptyEventsDict;
5853

5954
return typeDesc;
6055
}
6156

62-
internal static Dictionary<string, ComEventDesc> EmptyEvents {
63-
get { return _EmptyEventsDict; }
64-
}
57+
internal static Dictionary<string, ComEventDesc> EmptyEvents => _EmptyEventsDict;
6558

66-
internal Hashtable Funcs {
67-
get { return _funcs; }
68-
set { _funcs = value; }
69-
}
59+
internal ConcurrentDictionary<string, ComMethodDesc> Funcs { get; set; }
7060

71-
internal Hashtable Puts {
72-
get { return _puts; }
73-
set { _puts = value; }
74-
}
61+
internal ConcurrentDictionary<string, ComMethodDesc> Puts { get; set; }
7562

76-
internal Hashtable PutRefs {
77-
set { _putRefs = value; }
78-
}
63+
internal ConcurrentDictionary<string, ComMethodDesc> PutRefs { get; set; }
7964

80-
internal Dictionary<string, ComEventDesc> Events {
81-
get { return _events; }
82-
set { _events = value; }
83-
}
65+
internal Dictionary<string, ComEventDesc> Events { get; set; }
8466

8567
internal bool TryGetFunc(string name, out ComMethodDesc method) {
86-
name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
87-
if (_funcs.ContainsKey(name)) {
88-
method = _funcs[name] as ComMethodDesc;
68+
name = name.ToUpper(CultureInfo.InvariantCulture);
69+
if (Funcs.TryGetValue(name, out method)) {
8970
return true;
9071
}
91-
method = null;
72+
9273
return false;
9374
}
9475

9576
internal void AddFunc(string name, ComMethodDesc method) {
96-
name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
97-
lock (_funcs) {
98-
_funcs[name] = method;
99-
}
77+
name = name.ToUpper(CultureInfo.InvariantCulture);
78+
Funcs[name] = method;
10079
}
10180

10281
internal bool TryGetPut(string name, out ComMethodDesc method) {
103-
name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
104-
if (_puts.ContainsKey(name)) {
105-
method = _puts[name] as ComMethodDesc;
82+
name = name.ToUpper(CultureInfo.InvariantCulture);
83+
if (Puts.TryGetValue(name, out method)) {
10684
return true;
10785
}
108-
method = null;
86+
10987
return false;
11088
}
11189

11290
internal void AddPut(string name, ComMethodDesc method) {
113-
name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
114-
lock (_puts) {
115-
_puts[name] = method;
116-
}
91+
name = name.ToUpper(CultureInfo.InvariantCulture);
92+
Puts[name] = method;
11793
}
11894

11995
internal bool TryGetPutRef(string name, out ComMethodDesc method) {
120-
name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
121-
if (_putRefs.ContainsKey(name)) {
122-
method = _putRefs[name] as ComMethodDesc;
96+
name = name.ToUpper(CultureInfo.InvariantCulture);
97+
if (PutRefs.TryGetValue(name, out method)) {
12398
return true;
12499
}
125-
method = null;
100+
126101
return false;
127102
}
128103
internal void AddPutRef(string name, ComMethodDesc method) {
129-
name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
130-
lock (_putRefs) {
131-
_putRefs[name] = method;
132-
}
104+
name = name.ToUpper(CultureInfo.InvariantCulture);
105+
PutRefs[name] = method;
106+
133107
}
134108

135109
internal bool TryGetEvent(string name, out ComEventDesc @event) {
136-
name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
137-
return _events.TryGetValue(name, out @event);
110+
name = name.ToUpper(CultureInfo.InvariantCulture);
111+
return Events.TryGetValue(name, out @event);
138112
}
139113

140114
internal string[] GetMemberNames(bool dataOnly) {
141115
var names = new Dictionary<string, object>();
142116

143-
lock (_funcs) {
144-
foreach (ComMethodDesc func in _funcs.Values) {
117+
lock (Funcs) {
118+
foreach (ComMethodDesc func in Funcs.Values) {
145119
if (!dataOnly || func.IsDataMember) {
146120
names.Add(func.Name, null);
147121
}
148122
}
149123
}
150124

151125
if (!dataOnly) {
152-
lock (_puts) {
153-
foreach (ComMethodDesc func in _puts.Values) {
126+
lock (Puts) {
127+
foreach (ComMethodDesc func in Puts.Values) {
154128
if (!names.ContainsKey(func.Name)) {
155129
names.Add(func.Name, null);
156130
}
157131
}
158132
}
159133

160-
lock (_putRefs) {
161-
foreach (ComMethodDesc func in _putRefs.Values) {
134+
lock (PutRefs) {
135+
foreach (ComMethodDesc func in PutRefs.Values) {
162136
if (!names.ContainsKey(func.Name)) {
163137
names.Add(func.Name, null);
164138
}
165139
}
166140
}
167141

168-
if (_events != null && _events.Count > 0) {
169-
foreach (string name in _events.Keys) {
142+
if (Events != null && Events.Count > 0) {
143+
foreach (string name in Events.Keys) {
170144
if (!names.ContainsKey(name)) {
171145
names.Add(name, null);
172146
}
@@ -180,30 +154,22 @@ internal string[] GetMemberNames(bool dataOnly) {
180154
}
181155

182156
// this property is public - accessed by an AST
183-
public string TypeName {
184-
get { return _typeName; }
185-
}
157+
public string TypeName => _typeName;
186158

187-
internal string Documentation {
188-
get { return _documentation; }
189-
}
159+
internal string Documentation => _documentation;
190160

191161
// this property is public - accessed by an AST
192162
public ComTypeLibDesc TypeLib { get; }
193163

194164
internal Guid Guid { get; set; }
195165

196-
internal ComMethodDesc GetItem {
197-
get { return _getItem; }
198-
}
166+
internal ComMethodDesc GetItem => _getItem;
199167

200168
internal void EnsureGetItem(ComMethodDesc candidate) {
201169
Interlocked.CompareExchange(ref _getItem, candidate, null);
202170
}
203171

204-
internal ComMethodDesc SetItem {
205-
get { return _setItem; }
206-
}
172+
internal ComMethodDesc SetItem => _setItem;
207173

208174
internal void EnsureSetItem(ComMethodDesc candidate) {
209175
Interlocked.CompareExchange(ref _setItem, candidate, null);

Src/Microsoft.Dynamic/ComInterop/IDispatchComObject.cs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
// See the LICENSE file in the project root for more information.
44

55
#if FEATURE_COM
6-
using System.Linq.Expressions;
76

87
using System;
9-
using System.Collections;
8+
using System.Collections.Concurrent;
109
using System.Collections.Generic;
1110
using System.Diagnostics;
11+
using System.Dynamic;
1212
using System.Globalization;
13+
using System.Linq.Expressions;
1314
using System.Reflection;
1415
using System.Runtime.InteropServices;
15-
using System.Security;
16-
using System.Security.Permissions;
16+
1717
using ComTypes = System.Runtime.InteropServices.ComTypes;
18-
using System.Dynamic;
1918

2019
namespace Microsoft.Scripting.ComInterop {
2120

@@ -501,9 +500,9 @@ private void EnsureScanDefinedMethods() {
501500

502501
ComMethodDesc getItem = null;
503502
ComMethodDesc setItem = null;
504-
Hashtable funcs = new Hashtable(typeAttr.cFuncs);
505-
Hashtable puts = new Hashtable();
506-
Hashtable putrefs = new Hashtable();
503+
ConcurrentDictionary<string, ComMethodDesc> funcs = new ConcurrentDictionary<string, ComMethodDesc>(Environment.ProcessorCount, typeAttr.cFuncs);
504+
ConcurrentDictionary<string, ComMethodDesc> puts = new ConcurrentDictionary<string, ComMethodDesc>();
505+
ConcurrentDictionary<string, ComMethodDesc> putrefs = new ConcurrentDictionary<string, ComMethodDesc>();
507506

508507
for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++) {
509508
IntPtr funcDescHandleToRelease = IntPtr.Zero;
@@ -520,7 +519,7 @@ private void EnsureScanDefinedMethods() {
520519
string name = method.Name.ToUpper(CultureInfo.InvariantCulture);
521520

522521
if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0) {
523-
puts.Add(name, method);
522+
puts.TryAdd(name, method);
524523

525524
// for the special dispId == 0, we need to store
526525
// the method descriptor for the Do(SetItem) binder.
@@ -530,7 +529,7 @@ private void EnsureScanDefinedMethods() {
530529
continue;
531530
}
532531
if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0) {
533-
putrefs.Add(name, method);
532+
putrefs.TryAdd(name, method);
534533
// for the special dispId == 0, we need to store
535534
// the method descriptor for the Do(SetItem) binder.
536535
if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) {
@@ -540,11 +539,11 @@ private void EnsureScanDefinedMethods() {
540539
}
541540

542541
if (funcDesc.memid == ComDispIds.DISPID_NEWENUM) {
543-
funcs.Add("GETENUMERATOR", method);
542+
funcs.TryAdd("GETENUMERATOR", method);
544543
continue;
545544
}
546545

547-
funcs.Add(name, method);
546+
funcs.TryAdd(name, method);
548547

549548
// for the special dispId == 0, we need to store the method descriptor
550549
// for the Do(GetItem) binder.

0 commit comments

Comments
 (0)