Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit 4a609eb

Browse files
Merge pull request #799 from xamarin/lets-async-start
add some basic parallelism to improve performance
2 parents 3084620 + 31fe113 commit 4a609eb

12 files changed

+199
-84
lines changed

Diff for: SwiftReflector/ErrorHandling.cs

+32-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace SwiftReflector {
1313
public class ErrorHandling {
14+
object messagesLock = new object ();
1415
List<ReflectorError> messages;
1516

1617
public ErrorHandling ()
@@ -37,37 +38,61 @@ public IEnumerable<ReflectorError> Warnings {
3738

3839
public void Add (ErrorHandling eh)
3940
{
40-
messages.AddRange (eh.messages);
41+
lock (messagesLock) {
42+
lock (eh.messagesLock) {
43+
messages.AddRange (eh.messages);
44+
}
45+
}
4146
}
4247

4348
public void Add (params ReflectorError [] errors)
4449
{
45-
messages.AddRange (errors);
50+
lock (messagesLock) {
51+
messages.AddRange (errors);
52+
}
4653
}
4754

4855
public void Add (Exception exception)
4956
{
57+
lock (messagesLock) {
5058
#if CRASH_ON_EXCEPTION
5159
ExceptionDispatchInfo.Capture (exception).Throw ();
5260
#else
53-
messages.Add (new ReflectorError (exception));
61+
messages.Add (new ReflectorError (exception));
5462
#endif
63+
}
5564
}
5665

5766
public bool AnyMessages {
58-
get { return messages.Count > 0; }
67+
get {
68+
lock (messagesLock) {
69+
return messages.Count > 0;
70+
}
71+
}
5972
}
6073

6174
public bool AnyErrors {
62-
get { return messages.Any ((v) => !v.IsWarning); }
75+
get {
76+
lock (messagesLock) {
77+
return messages.Any ((v) => !v.IsWarning);
78+
}
79+
}
6380
}
6481

6582
public int WarningCount {
66-
get { return messages.Count ((v) => v.IsWarning); }
83+
get {
84+
lock (messagesLock) {
85+
return messages.Count ((v) => v.IsWarning);
86+
}
87+
}
6788
}
6889

6990
public int ErrorCount {
70-
get { return messages.Count ((v) => !v.IsWarning); }
91+
get {
92+
lock (messagesLock) {
93+
return messages.Count ((v) => !v.IsWarning);
94+
}
95+
}
7196
}
7297

7398
public int Show (int verbosity)

Diff for: SwiftReflector/Inventory/ClassInventory.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ public override void Add (TLDefinition tld, Stream srcStm)
2222
return;
2323
SwiftName className = ToClassName (tld);
2424
SwiftClassName formalName = ToFormalClassName (tld);
25-
ClassContents contents = null;
26-
if (!values.TryGetValue (className, out contents)) {
27-
contents = new ClassContents (formalName, sizeofMachinePointer);
28-
values.Add (className, contents);
25+
lock (valuesLock) {
26+
ClassContents contents = null;
27+
if (!values.TryGetValue (className, out contents)) {
28+
contents = new ClassContents (formalName, sizeofMachinePointer);
29+
values.Add (className, contents);
30+
}
31+
contents.Add (tld, srcStm);
2932
}
30-
contents.Add (tld, srcStm);
3133
}
3234

3335
public static SwiftClassName ToFormalClassName (TLDefinition tld)

Diff for: SwiftReflector/Inventory/FunctionInventory.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ public override void Add (TLDefinition tld, Stream srcStm)
2222
if (tlf == null)
2323
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 10, $"expected a top-level function but got a {tld.GetType ().Name}");
2424

25-
OverloadInventory overloads = null;
26-
if (!values.TryGetValue (tlf.Name, out overloads)) {
27-
overloads = new OverloadInventory (tlf.Name, sizeofMachinePointer);
28-
values.Add (tlf.Name, overloads);
25+
lock (valuesLock) {
26+
OverloadInventory overloads = null;
27+
if (!values.TryGetValue (tlf.Name, out overloads)) {
28+
overloads = new OverloadInventory (tlf.Name, sizeofMachinePointer);
29+
values.Add (tlf.Name, overloads);
30+
}
31+
overloads.Add (tlf, srcStm);
2932
}
30-
overloads.Add (tlf, srcStm);
3133
}
3234

3335
public TLFunction ContainsEquivalentFunction (TLFunction func)

Diff for: SwiftReflector/Inventory/Inventory.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace SwiftReflector.Inventory {
1010
public abstract class Inventory<T> {
11+
protected object valuesLock = new object ();
1112
protected Dictionary<SwiftName, T> values = new Dictionary<SwiftName, T> ();
1213

1314
public IEnumerable<SwiftName> Names { get { return values.Keys; } }
@@ -17,7 +18,9 @@ public abstract class Inventory<T> {
1718

1819
public bool ContainsName (SwiftName name)
1920
{
20-
return values.ContainsKey (name);
21+
lock (valuesLock) {
22+
return values.ContainsKey (name);
23+
}
2124
}
2225
public bool ContainsName (string name)
2326
{
@@ -26,7 +29,9 @@ public bool ContainsName (string name)
2629

2730
public bool TryGetValue (SwiftName name, out T value)
2831
{
29-
return values.TryGetValue (name, out value);
32+
lock (valuesLock) {
33+
return values.TryGetValue (name, out value);
34+
}
3035
}
3136

3237
public bool TryGetValue (string name, out T value)

Diff for: SwiftReflector/Inventory/ModuleInventory.cs

+33-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using SwiftReflector.Demangling;
1212
using ObjCRuntime;
1313
using SwiftRuntimeLibrary;
14+
using System.Threading.Tasks;
1415

1516
namespace SwiftReflector.Inventory {
1617
public class ModuleInventory : Inventory<ModuleContents> {
@@ -24,12 +25,14 @@ public int SizeofMachinePointer {
2425

2526
public override void Add (TLDefinition tld, Stream srcStm)
2627
{
27-
ModuleContents module = null;
28-
if (!values.TryGetValue (tld.Module, out module)) {
29-
module = new ModuleContents (tld.Module, SizeofMachinePointer);
30-
values.Add (tld.Module, module);
28+
lock (valuesLock) {
29+
ModuleContents module = null;
30+
if (!values.TryGetValue (tld.Module, out module)) {
31+
module = new ModuleContents (tld.Module, SizeofMachinePointer);
32+
values.Add (tld.Module, module);
33+
}
34+
module.Add (tld, srcStm);
3135
}
32-
module.Add (tld, srcStm);
3336
}
3437

3538
public IEnumerable<SwiftName> ModuleNames {
@@ -111,6 +114,23 @@ public static ModuleInventory FromFile (string pathToDynamicLibrary, ErrorHandli
111114
}
112115
}
113116

117+
public static async Task<ModuleInventory> FromFilesAsync (IEnumerable<string> pathsToLibraryFiles, ErrorHandling errors)
118+
{
119+
var streams = pathsToLibraryFiles.Select (path => new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read)).ToList ();
120+
if (streams.Count == 0)
121+
return null;
122+
var inventory = new ModuleInventory ();
123+
try {
124+
var tasks = streams.Select (stm => FromStreamIntoAsync (stm, inventory, errors, stm.Name));
125+
await Task.WhenAll (tasks);
126+
} finally {
127+
foreach (var stm in streams) {
128+
stm.Dispose ();
129+
}
130+
}
131+
return inventory;
132+
}
133+
114134
public static ModuleInventory FromFiles (IEnumerable<string> pathsToLibraryFiles, ErrorHandling errors)
115135
{
116136
ModuleInventory inventory = null;
@@ -124,6 +144,14 @@ public static ModuleInventory FromFiles (IEnumerable<string> pathsToLibraryFiles
124144
return inventory;
125145
}
126146

147+
static async Task<ModuleInventory> FromStreamIntoAsync (Stream stm, ModuleInventory inventory,
148+
ErrorHandling errors, string fileName = null)
149+
{
150+
return await Task.Run (() => {
151+
return FromStreamInto (stm, inventory, errors, fileName);
152+
});
153+
}
154+
127155
static ModuleInventory FromStreamInto (Stream stm, ModuleInventory inventory,
128156
ErrorHandling errors, string fileName = null)
129157
{

Diff for: SwiftReflector/Inventory/OverloadInventory.cs

+9-7
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ public OverloadInventory (SwiftName name, int sizeofMachinePointer)
2121

2222
public override void Add (TLDefinition tld, Stream srcStm)
2323
{
24-
TLFunction tlf = tld as TLFunction;
25-
if (tlf == null)
26-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 11, $"expected a top-level function but got a {tld.GetType ().Name}");
27-
if (Functions.Exists (f => tlf.MangledName == f.MangledName)) {
28-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 12, $"duplicate function found for {tlf.MangledName}");
29-
} else {
30-
Functions.Add (tlf);
24+
lock (valuesLock) {
25+
TLFunction tlf = tld as TLFunction;
26+
if (tlf == null)
27+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 11, $"expected a top-level function but got a {tld.GetType ().Name}");
28+
if (Functions.Exists (f => tlf.MangledName == f.MangledName)) {
29+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 12, $"duplicate function found for {tlf.MangledName}");
30+
} else {
31+
Functions.Add (tlf);
32+
}
3133
}
3234
}
3335

Diff for: SwiftReflector/Inventory/PropertyInventory.cs

+16-14
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,23 @@ public PropertyInventory (int sizeofMachinePointer)
1919

2020
public override void Add (TLDefinition tld, Stream srcStm)
2121
{
22-
TLFunction tlf = tld as TLFunction;
23-
if (tlf == null)
24-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 7, $"Expected a TLFunction for a property but got a {tld.GetType ().Name}.");
25-
26-
SwiftPropertyType prop = tlf.Signature as SwiftPropertyType;
27-
if (prop == null)
28-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 8, $"Expected a function of property type but got a {tlf.Signature.GetType ().Name}.");
29-
30-
PropertyContents contents = null;
31-
SwiftName nameToUse = prop.PrivateName ?? prop.Name;
32-
if (!values.TryGetValue (nameToUse, out contents)) {
33-
contents = new PropertyContents (tlf.Class, nameToUse, sizeofMachinePointer);
34-
values.Add (nameToUse, contents);
22+
lock (valuesLock) {
23+
TLFunction tlf = tld as TLFunction;
24+
if (tlf == null)
25+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 7, $"Expected a TLFunction for a property but got a {tld.GetType ().Name}.");
26+
27+
SwiftPropertyType prop = tlf.Signature as SwiftPropertyType;
28+
if (prop == null)
29+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 8, $"Expected a function of property type but got a {tlf.Signature.GetType ().Name}.");
30+
31+
PropertyContents contents = null;
32+
SwiftName nameToUse = prop.PrivateName ?? prop.Name;
33+
if (!values.TryGetValue (nameToUse, out contents)) {
34+
contents = new PropertyContents (tlf.Class, nameToUse, sizeofMachinePointer);
35+
values.Add (nameToUse, contents);
36+
}
37+
contents.Add (tlf, prop);
3538
}
36-
contents.Add (tlf, prop);
3739
}
3840

3941
public PropertyContents PropertyWithName (SwiftName name)

Diff for: SwiftReflector/Inventory/ProtocolInventory.cs

+9-7
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ public ProtocolInventory (int sizeofMachinePointer)
1515

1616
public override void Add (TLDefinition tld, Stream srcStm)
1717
{
18-
SwiftName className = ClassInventory.ToClassName (tld);
19-
SwiftClassName formalName = ClassInventory.ToFormalClassName (tld);
20-
ProtocolContents contents = null;
21-
if (!values.TryGetValue (className, out contents)) {
22-
contents = new ProtocolContents (formalName, sizeofMachinePointer);
23-
values.Add (className, contents);
18+
lock (valuesLock) {
19+
SwiftName className = ClassInventory.ToClassName (tld);
20+
SwiftClassName formalName = ClassInventory.ToFormalClassName (tld);
21+
ProtocolContents contents = null;
22+
if (!values.TryGetValue (className, out contents)) {
23+
contents = new ProtocolContents (formalName, sizeofMachinePointer);
24+
values.Add (className, contents);
25+
}
26+
contents.Add (tld, srcStm);
2427
}
25-
contents.Add (tld, srcStm);
2628
}
2729
}
2830
}

Diff for: SwiftReflector/Inventory/VariableInventory.cs

+17-15
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,25 @@ public VariableInventory (int sizeofMachinePointer)
1616
}
1717
public override void Add (TLDefinition tld, Stream srcStm)
1818
{
19-
TLVariable vari = tld as TLVariable;
20-
if (vari != null) {
21-
VariableContents contents = GoGetIt (vari.Name);
22-
if (contents.Variable != null)
23-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 4, $"duplicate variable {vari.Name.Name}.");
24-
contents.Variable = vari;
25-
return;
26-
}
19+
lock (valuesLock) {
20+
TLVariable vari = tld as TLVariable;
21+
if (vari != null) {
22+
VariableContents contents = GoGetIt (vari.Name);
23+
if (contents.Variable != null)
24+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 4, $"duplicate variable {vari.Name.Name}.");
25+
contents.Variable = vari;
26+
return;
27+
}
2728

28-
TLFunction tlf = tld as TLFunction;
29-
if (tlf != null) {
30-
VariableContents contents = GoGetIt (tlf.Name);
31-
contents.Addressors.Add (tlf);
32-
return;
33-
}
29+
TLFunction tlf = tld as TLFunction;
30+
if (tlf != null) {
31+
VariableContents contents = GoGetIt (tlf.Name);
32+
contents.Addressors.Add (tlf);
33+
return;
34+
}
3435

35-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 5, $"expected a top-level function or top-level variable but got a {tld.GetType ().Name}");
36+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 5, $"expected a top-level function or top-level variable but got a {tld.GetType ().Name}");
37+
}
3638

3739
}
3840

Diff for: SwiftReflector/Inventory/WitnessInventory.cs

+10-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace SwiftReflector.Inventory {
1313
public class WitnessInventory {
14+
object valuesLock = new object ();
1415
Dictionary<string, TLFunction> values = new Dictionary<string, TLFunction> ();
1516
int sizeofMachinePointer;
1617

@@ -21,14 +22,16 @@ public WitnessInventory (int sizeofMachinePointer)
2122

2223
public void Add (TLDefinition tld, Stream srcStm)
2324
{
24-
TLFunction tlf = tld as TLFunction;
25-
if (tlf == null)
26-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 9, $"Expected a TLFunction for a witness table but got a {tld.GetType ().Name}.");
25+
lock (valuesLock) {
26+
TLFunction tlf = tld as TLFunction;
27+
if (tlf == null)
28+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 9, $"Expected a TLFunction for a witness table but got a {tld.GetType ().Name}.");
2729

28-
if (values.ContainsKey (tlf.MangledName))
29-
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 10, $"Already received witness table entry for {tlf.MangledName}.");
30-
values.Add (tlf.MangledName, tlf);
31-
LoadWitnessTable (tlf, srcStm);
30+
if (values.ContainsKey (tlf.MangledName))
31+
throw ErrorHelper.CreateError (ReflectorError.kInventoryBase + 10, $"Already received witness table entry for {tlf.MangledName}.");
32+
values.Add (tlf.MangledName, tlf);
33+
LoadWitnessTable (tlf, srcStm);
34+
}
3235
}
3336

3437
public IEnumerable<string> MangledNames { get { return values.Keys; } }

0 commit comments

Comments
 (0)