Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 22832f7

Browse files
author
Mikhail Arkhipov
authored
Add class member lock protection (microsoft#1491)
* Add class member lock protection * usings * Fix null ref
1 parent 51ccb26 commit 22832f7

File tree

2 files changed

+29
-19
lines changed

2 files changed

+29
-19
lines changed

src/Analysis/Ast/Impl/Types/PythonClassType.Generics.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ namespace Microsoft.Python.Analysis.Types {
2525
internal partial class PythonClassType {
2626
private readonly ReentrancyGuard<IPythonClassType> _genericSpecializationGuard = new ReentrancyGuard<IPythonClassType>();
2727
private readonly ReentrancyGuard<IPythonClassType> _genericResolutionGuard = new ReentrancyGuard<IPythonClassType>();
28-
private readonly object _genericParameterLock = new object();
2928

3029
private bool _isGeneric;
3130
private Dictionary<string, PythonClassType> _specificTypeCache;
@@ -60,7 +59,7 @@ internal partial class PythonClassType {
6059
/// B[int] inherits from A[int, str]
6160
/// </summary>
6261
public IPythonType CreateSpecificType(IArgumentSet args) {
63-
lock (_genericParameterLock) {
62+
lock (_membersLock) {
6463
var newGenericTypeParameters = GetTypeParameters();
6564
var newBases = new List<IPythonType>();
6665

@@ -161,18 +160,18 @@ private IGenericTypeParameter[] GetTypeParameters() {
161160
}
162161
}
163162
}
164-
165163
return fromBases.ToArray();
166164
}
167165

168166
/// <summary>
169167
/// Given an argument set, returns a dictionary mapping generic type parameter to the supplied specific
170168
/// type from arguments.
171169
/// </summary>
172-
private IReadOnlyDictionary<IGenericTypeParameter, IPythonType> GetSpecificTypes(IArgumentSet args,
173-
IGenericTypeParameter[] genericTypeParameters,
174-
List<IPythonType> newBases) {
175-
170+
private IReadOnlyDictionary<IGenericTypeParameter, IPythonType> GetSpecificTypes(
171+
IArgumentSet args,
172+
IReadOnlyList<IGenericTypeParameter> genericTypeParameters,
173+
ICollection<IPythonType> newBases
174+
) {
176175
// For now, map each type parameter to itself, and we can fill in the value as we go
177176
var genericTypeToSpecificType = genericTypeParameters.ToDictionary(gtp => gtp, gtp => gtp as IPythonType);
178177

@@ -240,7 +239,7 @@ private IReadOnlyDictionary<IGenericTypeParameter, IPythonType> GetSpecificTypes
240239
if (arg.Value is IMember member) {
241240
var type = member.GetPythonType();
242241
if (!type.IsUnknown()) {
243-
var gtd = gtIndex < genericTypeParameters.Length ? genericTypeParameters[gtIndex] : null;
242+
var gtd = gtIndex < genericTypeParameters.Count ? genericTypeParameters[gtIndex] : null;
244243
if (gtd != null && genericTypeToSpecificType.TryGetValue(gtd, out var s) && s is IGenericTypeParameter) {
245244
genericTypeToSpecificType[gtd] = type;
246245
}
@@ -304,7 +303,7 @@ private void StoreGenericParameters(
304303
/// <param name="gt">Generic type (Generic[T1, T2, ...], A[T1, T2, ..], etc.).</param>
305304
/// <param name="argumentValue">Argument value passed to the class constructor.</param>
306305
/// <param name="specificTypes">Dictionary or name (T1) to specific type to populate.</param>
307-
private void GetSpecificTypeFromArgumentValue(IGenericType gt, object argumentValue, IDictionary<IGenericTypeParameter, IPythonType> specificTypes) {
306+
private static void GetSpecificTypeFromArgumentValue(IGenericType gt, object argumentValue, IDictionary<IGenericTypeParameter, IPythonType> specificTypes) {
308307
switch (argumentValue) {
309308
case IPythonDictionary dict when gt.Parameters.Count == 2:
310309
var keyType = dict.Keys.FirstOrDefault()?.GetPythonType();

src/Analysis/Ast/Impl/Types/PythonClassType.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ internal partial class PythonClassType : PythonType, IPythonClassType, IEquatabl
3535
private static readonly string[] _classMethods = { "mro", "__dict__", @"__weakref__" };
3636

3737
private readonly ReentrancyGuard<IPythonClassType> _memberGuard = new ReentrancyGuard<IPythonClassType>();
38+
private readonly object _membersLock = new object();
39+
3840
private string _genericName;
3941
private List<IPythonType> _bases;
4042
private IReadOnlyList<IPythonType> _mro;
@@ -60,18 +62,22 @@ public PythonClassType(ClassDefinition classDefinition, Location location, Built
6062
public override PythonMemberType MemberType => PythonMemberType.Class;
6163

6264
public override IEnumerable<string> GetMemberNames() {
63-
var names = new HashSet<string>();
64-
names.UnionWith(Members.Keys);
65-
foreach (var m in Mro.Skip(1)) {
66-
names.UnionWith(m.GetMemberNames());
65+
lock (_membersLock) {
66+
var names = new HashSet<string>(Members.Keys);
67+
foreach (var m in Mro.Skip(1)) {
68+
names.UnionWith(m.GetMemberNames());
69+
}
70+
return DeclaringModule.Interpreter.LanguageVersion.Is3x() ? names.Concat(_classMethods).Distinct() : names;
6771
}
68-
return DeclaringModule.Interpreter.LanguageVersion.Is3x() ? names.Concat(_classMethods).Distinct() : names;
6972
}
7073

7174
public override IMember GetMember(string name) {
72-
// Push/Pop should be lock protected.
73-
if (Members.TryGetValue(name, out var member)) {
74-
return member;
75+
IMember member;
76+
77+
lock (_membersLock) {
78+
if (Members.TryGetValue(name, out member)) {
79+
return member;
80+
}
7581
}
7682

7783
// Special case names that we want to add to our own Members dict
@@ -159,12 +165,17 @@ public override IMember Index(IPythonInstance instance, IArgumentSet args) {
159165

160166
return fromBases ?? defaultReturn;
161167
}
162-
163168
#endregion
164169

165170
#region IPythonClass
166171
public ClassDefinition ClassDefinition => DeclaringModule.GetAstNode<ClassDefinition>(this);
167-
public IReadOnlyList<IPythonType> Bases => _bases;
172+
public IReadOnlyList<IPythonType> Bases {
173+
get {
174+
lock(_membersLock) {
175+
return _bases?.ToArray();
176+
}
177+
}
178+
}
168179

169180
public IReadOnlyList<IPythonType> Mro {
170181
get {

0 commit comments

Comments
 (0)