Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improves thread safety of lazy initializations #641

Merged
merged 3 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions Mono.Cecil.Cil/MethodBody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,38 @@ public MetadataToken LocalVarToken {
}

public Collection<Instruction> Instructions {
get { return instructions ?? (instructions = new InstructionCollection (method)); }
get {
if (instructions == null)
Interlocked.CompareExchange (ref instructions, new InstructionCollection(method), null);
jbevain marked this conversation as resolved.
Show resolved Hide resolved

return instructions;
}
}

public bool HasExceptionHandlers {
get { return !exceptions.IsNullOrEmpty (); }
}

public Collection<ExceptionHandler> ExceptionHandlers {
get { return exceptions ?? (exceptions = new Collection<ExceptionHandler> ()); }
get {
if (exceptions == null)
Interlocked.CompareExchange (ref exceptions, new Collection<ExceptionHandler> (), null);

return exceptions;
}
}

public bool HasVariables {
get { return !variables.IsNullOrEmpty (); }
}

public Collection<VariableDefinition> Variables {
get { return variables ?? (variables = new VariableDefinitionCollection ()); }
get {
if (variables == null)
Interlocked.CompareExchange (ref variables, new VariableDefinitionCollection(), null);
jbevain marked this conversation as resolved.
Show resolved Hide resolved

return variables;
}
}

public ParameterDefinition ThisParameter {
Expand Down
58 changes: 50 additions & 8 deletions Mono.Cecil.Cil/Symbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using SR = System.Reflection;

using Mono.Collections.Generic;
Expand Down Expand Up @@ -118,23 +119,38 @@ public bool HasScopes {
}

public Collection<ScopeDebugInformation> Scopes {
get { return scopes ?? (scopes = new Collection<ScopeDebugInformation> ()); }
get {
if (scopes == null)
Interlocked.CompareExchange (ref scopes, new Collection<ScopeDebugInformation> (), null);

return scopes;
}
}

public bool HasVariables {
get { return !variables.IsNullOrEmpty (); }
}

public Collection<VariableDebugInformation> Variables {
get { return variables ?? (variables = new Collection<VariableDebugInformation> ()); }
get {
if (variables == null)
Interlocked.CompareExchange (ref variables, new Collection<VariableDebugInformation> (), null);

return variables;
}
}

public bool HasConstants {
get { return !constants.IsNullOrEmpty (); }
}

public Collection<ConstantDebugInformation> Constants {
get { return constants ?? (constants = new Collection<ConstantDebugInformation> ()); }
get {
if (constants == null)
Interlocked.CompareExchange (ref constants, new Collection<ConstantDebugInformation> (), null);

return constants;
}
}

internal ScopeDebugInformation ()
Expand Down Expand Up @@ -259,7 +275,12 @@ public bool HasCustomDebugInformations {
}

public Collection<CustomDebugInformation> CustomDebugInformations {
get { return custom_infos ?? (custom_infos = new Collection<CustomDebugInformation> ()); }
get {
if (custom_infos == null)
Interlocked.CompareExchange (ref custom_infos, new Collection<CustomDebugInformation> (), null);

return custom_infos;
}
}

internal DebugInformation ()
Expand Down Expand Up @@ -409,7 +430,13 @@ public bool HasTargets {
}

public Collection<ImportTarget> Targets {
get { return targets ?? (targets = new Collection<ImportTarget> ()); }
get
{
if (targets == null)
Interlocked.CompareExchange (ref targets, new Collection<ImportTarget> (), null);

return targets;
}
}

public ImportDebugInformation Parent {
Expand Down Expand Up @@ -488,11 +515,21 @@ public InstructionOffset CatchHandler {
}

public Collection<InstructionOffset> Yields {
get { return yields ?? (yields = new Collection<InstructionOffset> ()); }
get {
if (yields == null)
Interlocked.CompareExchange (ref yields, new Collection<InstructionOffset> (), null);

return yields;
}
}

public Collection<InstructionOffset> Resumes {
get { return resumes ?? (resumes = new Collection<InstructionOffset> ()); }
get {
if (resumes == null)
Interlocked.CompareExchange (ref resumes, new Collection<InstructionOffset> (), null);

return resumes;
}
}

public Collection<MethodDefinition> ResumeMethods {
Expand Down Expand Up @@ -641,7 +678,12 @@ public bool HasSequencePoints {
}

public Collection<SequencePoint> SequencePoints {
get { return sequence_points ?? (sequence_points = new Collection<SequencePoint> ()); }
get {
if (sequence_points == null)
Interlocked.CompareExchange (ref sequence_points, new Collection<SequencePoint> (), null);

return sequence_points;
}
}

public ScopeDebugInformation Scope {
Expand Down
8 changes: 6 additions & 2 deletions Mono.Cecil/ArrayType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

using System;
using System.Text;
using System.Threading;
using Mono.Collections.Generic;
using MD = Mono.Cecil.Metadata;

Expand Down Expand Up @@ -57,8 +58,11 @@ public Collection<ArrayDimension> Dimensions {
if (dimensions != null)
return dimensions;

dimensions = new Collection<ArrayDimension> ();
dimensions.Add (new ArrayDimension ());
var empty_dimensions = new Collection<ArrayDimension> ();
empty_dimensions.Add (new ArrayDimension ());

Interlocked.CompareExchange (ref dimensions, empty_dimensions, null);

return dimensions;
}
}
Expand Down
5 changes: 3 additions & 2 deletions Mono.Cecil/AssemblyDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

using System;
using System.IO;

using System.Threading;
using Mono.Collections.Generic;

namespace Mono.Cecil {
Expand Down Expand Up @@ -46,7 +46,8 @@ public Collection<ModuleDefinition> Modules {
if (main_module.HasImage)
return main_module.Read (ref modules, this, (_, reader) => reader.ReadModules ());

return modules = new Collection<ModuleDefinition> (1) { main_module };
Interlocked.CompareExchange (ref modules, new Collection<ModuleDefinition> (1) { main_module }, null);
return modules;
}
}

Expand Down
7 changes: 5 additions & 2 deletions Mono.Cecil/AssemblyNameReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Threading;

namespace Mono.Cecil {

Expand Down Expand Up @@ -97,7 +98,7 @@ public byte [] PublicKeyToken {
var local_public_key_token = new byte [8];
Array.Copy (hash, (hash.Length - 8), local_public_key_token, 0, 8);
Array.Reverse (local_public_key_token, 0, 8);
public_key_token = local_public_key_token; // publish only once finished (required for thread-safety)
Interlocked.CompareExchange (ref public_key_token, local_public_key_token, null); // publish only once finished (required for thread-safety)
}
return public_key_token ?? Empty<byte>.Array;
}
Expand Down Expand Up @@ -160,7 +161,9 @@ public string FullName {
builder.Append ("Retargetable=Yes");
}

return full_name = builder.ToString ();
Interlocked.CompareExchange (ref full_name, builder.ToString (), null);

return full_name;
}
}

Expand Down
51 changes: 33 additions & 18 deletions Mono.Cecil/CustomAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

using System;
using System.Diagnostics;
using System.Threading;
using Mono.Collections.Generic;

namespace Mono.Cecil {
Expand Down Expand Up @@ -105,7 +106,10 @@ public Collection<CustomAttributeArgument> ConstructorArguments {
get {
Resolve ();

return arguments ?? (arguments = new Collection<CustomAttributeArgument> ());
if (arguments == null)
Interlocked.CompareExchange (ref arguments, new Collection<CustomAttributeArgument> (), null);

return arguments;
}
}

Expand All @@ -121,7 +125,10 @@ public Collection<CustomAttributeNamedArgument> Fields {
get {
Resolve ();

return fields ?? (fields = new Collection<CustomAttributeNamedArgument> ());
if (fields == null)
Interlocked.CompareExchange (ref fields, new Collection<CustomAttributeNamedArgument> (), null);

return fields;
}
}

Expand All @@ -137,7 +144,10 @@ public Collection<CustomAttributeNamedArgument> Properties {
get {
Resolve ();

return properties ?? (properties = new Collection<CustomAttributeNamedArgument> ());
if (properties == null)
Interlocked.CompareExchange (ref properties, new Collection<CustomAttributeNamedArgument> (), null);

return properties;
}
}

Expand Down Expand Up @@ -185,21 +195,26 @@ void Resolve ()
if (resolved || !HasImage)
return;

Module.Read (this, (attribute, reader) => {
try {
reader.ReadCustomAttributeSignature (attribute);
resolved = true;
} catch (ResolutionException) {
if (arguments != null)
arguments.Clear ();
if (fields != null)
fields.Clear ();
if (properties != null)
properties.Clear ();

resolved = false;
}
});
lock (Module.SyncRoot) {
if (resolved)
return;

Module.Read (this, (attribute, reader) => {
try {
reader.ReadCustomAttributeSignature (attribute);
resolved = true;
} catch (ResolutionException) {
if (arguments != null)
arguments.Clear ();
if (fields != null)
fields.Clear ();
if (properties != null)
properties.Clear ();

resolved = false;
}
});
}
}
}
}
7 changes: 4 additions & 3 deletions Mono.Cecil/EventDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// Licensed under the MIT/X11 license.
//

using System.Threading;
using Mono.Collections.Generic;

namespace Mono.Cecil {
Expand Down Expand Up @@ -78,10 +79,10 @@ public Collection<MethodDefinition> OtherMethods {

InitializeMethods ();

if (other_methods != null)
return other_methods;
if (other_methods == null)
Interlocked.CompareExchange (ref other_methods, new Collection<MethodDefinition> (), null);

return other_methods = new Collection<MethodDefinition> ();
return other_methods;
}
}

Expand Down
13 changes: 11 additions & 2 deletions Mono.Cecil/FieldDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//

using System;
using System.Threading;
using Mono.Collections.Generic;

namespace Mono.Cecil {
Expand Down Expand Up @@ -37,7 +38,11 @@ void ResolveLayout ()
return;
}

offset = Module.Read (this, (field, reader) => reader.ReadFieldLayout (field));
lock (Module.SyncRoot) {
if (offset != Mixin.NotResolvedMarker)
return;
offset = Module.Read (this, (field, reader) => reader.ReadFieldLayout (field));
}
}

public bool HasLayoutInfo {
Expand Down Expand Up @@ -76,7 +81,11 @@ void ResolveRVA ()
if (!HasImage)
return;

rva = Module.Read (this, (field, reader) => reader.ReadFieldRVA (field));
lock (Module.SyncRoot) {
if (rva != Mixin.NotResolvedMarker)
return;
rva = Module.Read (this, (field, reader) => reader.ReadFieldRVA (field));
}
}

public int RVA {
Expand Down
9 changes: 7 additions & 2 deletions Mono.Cecil/GenericInstanceMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

using System;
using System.Text;

using System.Threading;
using Mono.Collections.Generic;

namespace Mono.Cecil {
Expand All @@ -24,7 +24,12 @@ public bool HasGenericArguments {
}

public Collection<TypeReference> GenericArguments {
get { return arguments ?? (arguments = new Collection<TypeReference> ()); }
get {
if (arguments == null)
Interlocked.CompareExchange (ref arguments, new Collection<TypeReference> (), null);

return arguments;
}
}

public override bool IsGenericInstance {
Expand Down
Loading