Skip to content

Commit e96cf9b

Browse files
author
Egor
authored
Merge pull request #21 from medegor44/ChakraCore_multithreading
Fix multithreading issue for ChakraCore, add multithreading tests for runners.
2 parents 0d1b479 + b545e00 commit e96cf9b

File tree

19 files changed

+1041
-91
lines changed

19 files changed

+1041
-91
lines changed

Src/EmbeddedScripts.CSharp.MonoEvaluator/EmbeddedScripts.CSharp.MonoEvaluator.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net461</TargetFramework>
5+
<LangVersion>latest</LangVersion>
56
</PropertyGroup>
67

78
<ItemGroup>

Src/EmbeddedScripts.CSharp.MonoEvaluator/MonoCSharpRunner.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
using System;
2-
using System.Data;
3-
using System.IO;
1+
using System.IO;
42
using System.Text;
3+
using System.Threading;
54
using System.Threading.Tasks;
65
using EmbeddedScripts.CSharp.MonoEvaluator.CodeGeneration;
76
using EmbeddedScripts.CSharp.MonoEvaluator.Hosting;
@@ -13,10 +12,11 @@ namespace EmbeddedScripts.CSharp.MonoEvaluator
1312
{
1413
public class MonoCSharpRunner : ICodeRunner, IEvaluator
1514
{
16-
private readonly StringBuilder _errorLogBuilder = new StringBuilder();
15+
private static int _nextRunnerId;
16+
private readonly StringBuilder _errorLogBuilder = new();
1717
private readonly Evaluator _evaluator;
18-
private readonly MonoSpecificCodeGenerator _codeGenerator = new MonoSpecificCodeGenerator();
19-
private readonly int _runnerId = new Random().Next(0, int.MaxValue);
18+
private readonly MonoSpecificCodeGenerator _codeGenerator = new();
19+
private readonly int _runnerId;
2020

2121
/// <summary>
2222
/// Evaluator doesn't throw any syntax exceptions. Instead, it just logged errors into StreamReportPrinter. So we using
@@ -42,6 +42,8 @@ public MonoCSharpRunner()
4242
_evaluator = new Evaluator(new CompilerContext(
4343
defaultSettings, new StreamReportPrinter(new StringWriter(_errorLogBuilder))));
4444

45+
_runnerId = Interlocked.Increment(ref _nextRunnerId);
46+
4547
HostFields.CreateNewEntry(_runnerId);
4648
var hostFieldsType = typeof(HostFields);
4749
_evaluator.ReferenceAssembly(hostFieldsType.Assembly);
@@ -61,9 +63,11 @@ public Task RunAsync(string code)
6163
public ICodeRunner Register<T>(T instance, string alias)
6264
{
6365
var instanceType = typeof(T);
66+
6467
HostFields.Get(_runnerId).Add(alias, instance);
6568

6669
_evaluator.TryReferenceAssembly(instanceType.Assembly);
70+
6771
var resolveLine =_codeGenerator.GenerateResolveLine(alias, instanceType, _runnerId);
6872
RunAsync(resolveLine);
6973

Src/EmbeddedScripts.JS.ChakraCore/ChakraCoreRunner.cs

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,69 @@ namespace EmbeddedScripts.JS.ChakraCore
66
{
77
public class ChakraCoreRunner : ICodeRunner, IEvaluator, IDisposable
88
{
9-
private readonly JsRuntime _runtime = new();
10-
private readonly TypeMapper _mapper;
11-
private readonly JsContext _context;
9+
private JsRuntime _runtime;
10+
private TypeMapper _mapper;
11+
private JsContext _context;
12+
private readonly ScriptDispatcher _dispatcher = new();
1213

1314
public ChakraCoreRunner()
1415
{
15-
_context = _runtime.CreateContext();
16-
_mapper = new(_context);
16+
_dispatcher.Invoke(() =>
17+
{
18+
_runtime = new();
19+
_context = _runtime.CreateContext();
20+
if (_context.IsValid)
21+
_context.AddRef();
22+
_mapper = new(_context);
23+
});
1724
}
1825

1926
public Task<T> EvaluateAsync<T>(string expression)
20-
{
21-
var val = _context.Evaluate(expression);
27+
{
28+
return Task.FromResult(_dispatcher.Invoke(() =>
29+
{
30+
var val = _context.Evaluate(expression);
2231

23-
return Task.FromResult(new TypeMapper(_context).Map<T>(val));
32+
return _mapper.Map<T>(val);
33+
}));
2434
}
25-
35+
2636
public Task RunAsync(string code)
2737
{
28-
_context.Evaluate(code);
38+
_dispatcher.Invoke(() =>
39+
{
40+
_context.Evaluate(code);
41+
});
2942

3043
return Task.CompletedTask;
3144
}
3245

3346
public ICodeRunner Register<T>(T obj, string alias)
3447
{
35-
_context.GlobalObject.AddProperty(alias, _mapper.Map(obj));
36-
48+
_dispatcher.Invoke(() =>
49+
{
50+
var val = _mapper.Map(obj);
51+
52+
val.AddRef();
53+
54+
_context.GlobalObject.AddProperty(alias, val);
55+
});
56+
3757
return this;
3858
}
3959

40-
public void Dispose() =>
41-
_runtime?.Dispose();
60+
public void Dispose()
61+
{
62+
_dispatcher.Invoke(() =>
63+
{
64+
if (_context.IsValid)
65+
_context.Release();
66+
67+
_runtime?.Dispose();
68+
});
69+
70+
_dispatcher.Dispose();
71+
_mapper.Dispose();
72+
}
4273
}
4374
}

Src/EmbeddedScripts.JS.ChakraCore/Hosting/JavaScriptContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ public static JavaScriptValue RunScript(string script, JavaScriptSourceContext s
220220
JavaScriptValue result;
221221
Native.ThrowIfError(Native.JsRunScript(JavaScriptValue.FromString(script),
222222
sourceContext, JavaScriptValue.FromString(sourceName), Native.JsParseScriptAttributes.None, out result));
223+
223224
return result;
224225
}
225226

Src/EmbeddedScripts.JS.ChakraCore/JsContext.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,21 @@ public JsContext(JavaScriptContext context)
1212
{
1313
_context = context;
1414
using (Scope)
15-
{
1615
GlobalObject = new JsValue(this, JavaScriptValue.GlobalObject);
17-
}
1816
}
1917

18+
public void AddRef()
19+
{
20+
_context.AddRef();
21+
}
22+
23+
public void Release()
24+
{
25+
_context.Release();
26+
}
27+
28+
public bool IsValid => _context.IsValid;
29+
2030
public JsScope Scope =>
2131
new (new (_context));
2232

@@ -26,7 +36,9 @@ public JsValue Evaluate(string expression)
2636
{
2737
try
2838
{
29-
return new JsValue(this, JavaScriptContext.RunScript(expression));
39+
var t = JavaScriptContext.RunScript(expression);
40+
41+
return new JsValue(this, t);
3042
}
3143
catch (JavaScriptScriptException e)
3244
{

Src/EmbeddedScripts.JS.ChakraCore/JsValue.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,25 @@ internal JsValue(JsContext context)
1313
using (_context.Scope)
1414
_innerValue = JavaScriptValue.CreateObject();
1515
}
16-
16+
1717
internal JsValue(JsContext context, JavaScriptValue value)
1818
{
1919
_context = context;
2020
_innerValue = value;
2121
}
2222

23+
public void AddRef()
24+
{
25+
using (_context.Scope)
26+
_innerValue.AddRef();
27+
}
28+
29+
public void Release()
30+
{
31+
using (_context.Scope)
32+
_innerValue.Release();
33+
}
34+
2335
public JsValue AddProperty(string name, JsValue value)
2436
{
2537
using (_context.Scope)
@@ -37,7 +49,7 @@ public JsValue GetProperty(string name)
3749
public override string ToString() =>
3850
_innerValue.ConvertToString().ToString();
3951

40-
public static implicit operator JavaScriptValue(JsValue value) =>
52+
public static implicit operator JavaScriptValue(JsValue value) =>
4153
value._innerValue;
4254
}
4355
}

0 commit comments

Comments
 (0)