Skip to content

Commit 1bcd1b0

Browse files
author
Andrey Ovsiankin
committed
Merge branch 'develop' into feature/compiler-v2
2 parents 45fabf5 + fefcfe3 commit 1bcd1b0

File tree

17 files changed

+667
-17
lines changed

17 files changed

+667
-17
lines changed

Build.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@
127127
<Exec Command="&quot;$(ToolFolder)/oscript.exe&quot; &quot;$(MSBuildProjectDirectory)\install\unicode-zipper.os&quot; unpack &quot;$(MSBuildProjectDirectory)\install\opm-0.16.2.ospx&quot; &quot;$(LibFolder)\tmp&quot;"/>
128128
<Exec Command="&quot;$(ToolFolder)/oscript.exe&quot; &quot;$(MSBuildProjectDirectory)\install\unicode-zipper.os&quot; unpack &quot;$(LibFolder)\tmp\content.zip&quot; &quot;$(LibFolder)/opm&quot;"/>
129129

130-
<Copy SourceFiles="$(MSBuildProjectDirectory)\install\oscript-config.exe" DestinationFolder="$(TempFolder)/%(PlatformItem.BinFolder)" />
131130
<Copy SourceFiles="$(MSBuildProjectDirectory)\install\package-loader.os" DestinationFolder="$(LibFolder)"/>
132131

133132
<DeleteTree Directories="$(LibFolder)\tmp"/>

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pipeline {
44
agent none
55

66
environment {
7-
ReleaseNumber = '1.5.0'
7+
ReleaseNumber = '1.6.0'
88
outputEnc = '65001'
99
}
1010

install/oscript-config.exe

-2.09 MB
Binary file not shown.

src/OneScript.DebugProtocol/EvaluatedVariableLocator.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class EvaluatedVariableLocator : IVariableLocator
1818
private int[] _path;
1919
private readonly int _stackFrameIndex;
2020
private readonly string _expression;
21+
private readonly int _threadId;
2122

2223
private Variable[] _variables;
2324

@@ -28,21 +29,24 @@ private EvaluatedVariableLocator(EvaluatedVariableLocator parent, int variableIn
2829
Array.Copy(parent._path, _path, parent._path.Length);
2930
_path[parent._path.Length] = variableIndex;
3031
_expression = parent._expression;
31-
}
32+
_threadId = parent._threadId;
33+
}
3234

33-
public EvaluatedVariableLocator(string expression, int stackFrameIndex)
35+
public EvaluatedVariableLocator(string expression, int threadId, int stackFrameIndex)
3436
{
3537
_stackFrameIndex = stackFrameIndex;
3638
_path = new int[0];
3739
_expression = expression;
38-
}
40+
_threadId = threadId;
41+
}
3942

40-
public EvaluatedVariableLocator(string expression, int stackFrameIndex, int variableIndex)
43+
public EvaluatedVariableLocator(string expression, int threadId, int stackFrameIndex, int variableIndex)
4144
{
4245
_stackFrameIndex = stackFrameIndex;
4346
_path = new int[] { variableIndex };
4447
_expression = expression;
45-
}
48+
_threadId = threadId;
49+
}
4650

4751
public Variable this[int index]
4852
{
@@ -53,7 +57,7 @@ public Variable this[int index]
5357
return _variables[index];
5458
}
5559
}
56-
60+
5761
public int Count
5862
{
5963
get
@@ -85,7 +89,7 @@ void IVariableLocator.Hydrate(IDebuggerService process)
8589
{
8690
if(_variables != null)
8791
return;
88-
var variables = process.GetEvaluatedVariables(_expression, 1, _stackFrameIndex, _path);
92+
var variables = process.GetEvaluatedVariables(_expression, _threadId, _stackFrameIndex, _path);
8993
_variables = variables;
9094
}
9195

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
8+
using System.Linq;
9+
using System.Threading.Tasks;
10+
using OneScript.Commons;
11+
using OneScript.StandardLibrary.Collections;
12+
using ScriptEngine.Machine;
13+
using ScriptEngine.Machine.Contexts;
14+
15+
namespace OneScript.StandardLibrary.Tasks
16+
{
17+
[ContextClass("ФоновоеЗадание", "BackgroundTask")]
18+
public class BackgroundTask : AutoContext<BackgroundTask>
19+
{
20+
private readonly MethodInfo _method;
21+
private readonly int _methIndex;
22+
23+
public BackgroundTask(IRuntimeContextInstance target, string methodName, ArrayImpl parameters = default)
24+
{
25+
Target = target;
26+
MethodName = methodName;
27+
if(parameters != default)
28+
Parameters = new ArrayImpl(parameters);
29+
30+
Identifier = new GuidWrapper();
31+
32+
_methIndex = Target.FindMethod(MethodName);
33+
_method = Target.GetMethodInfo(_methIndex);
34+
}
35+
36+
public Task WorkerTask { get; set; }
37+
38+
[ContextProperty("УникальныйИдентификатор","UUID")]
39+
public GuidWrapper Identifier { get; private set; }
40+
41+
[ContextProperty("ИмяМетода","MethodName")]
42+
public string MethodName { get; private set; }
43+
44+
[ContextProperty("Объект","Object")]
45+
public IRuntimeContextInstance Target { get; private set; }
46+
47+
[ContextProperty("Состояние", "State")]
48+
public TaskStateEnum State { get; private set; }
49+
50+
[ContextProperty("Параметры", "Parameters")]
51+
public IValue Parameters { get; private set; } = ValueFactory.Create();
52+
53+
[ContextProperty("Результат", "Result")]
54+
public IValue Result { get; private set; } = ValueFactory.Create();
55+
56+
[ContextProperty("ИнформацияОбОшибке", "ExceptionInfo")]
57+
public ExceptionInfoContext ExceptionInfo { get; private set; }
58+
59+
/// <summary>
60+
/// Ждать завершения задания указанное число миллисекунд
61+
/// </summary>
62+
/// <param name="timeout">Таймаут. Если ноль - ждать вечно</param>
63+
/// <returns>Истина - дождались завершения. Ложь - сработал таймаут</returns>
64+
[ContextMethod("ОжидатьЗавершения", "Wait")]
65+
public bool Wait(int timeout = 0)
66+
{
67+
timeout = BackgroundTasksManager.ConvertTimeout(timeout);
68+
69+
return WorkerTask.Wait(timeout);
70+
}
71+
72+
public void ExecuteOnCurrentThread()
73+
{
74+
if (State != TaskStateEnum.NotRunned)
75+
throw new RuntimeException(Locale.NStr("ru = 'Неверное состояние задачи';en = 'Incorrect task status'"));
76+
77+
var parameters = Parameters is ArrayImpl array ?
78+
array.ToArray() :
79+
new IValue[0];
80+
81+
try
82+
{
83+
State = TaskStateEnum.Running;
84+
if (_method.IsFunction)
85+
{
86+
Target.CallAsFunction(_methIndex, parameters, out var result);
87+
Result = result;
88+
}
89+
else
90+
{
91+
Target.CallAsProcedure(_methIndex, parameters);
92+
}
93+
94+
State = TaskStateEnum.Completed;
95+
}
96+
catch (RuntimeException exception)
97+
{
98+
State = TaskStateEnum.CompletedWithErrors;
99+
ExceptionInfo = new ExceptionInfoContext(exception);
100+
}
101+
}
102+
}
103+
}
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
using OneScript.Commons;
14+
using OneScript.StandardLibrary.Collections;
15+
using ScriptEngine;
16+
using ScriptEngine.Machine;
17+
using ScriptEngine.Machine.Contexts;
18+
19+
namespace OneScript.StandardLibrary.Tasks
20+
{
21+
[ContextClass("МенеджерФоновыхЗаданий", "BackgroundTasksManager")]
22+
public class BackgroundTasksManager : AutoContext<BackgroundTasksManager>, IDisposable
23+
{
24+
private readonly ScriptingEngine _engine;
25+
private List<BackgroundTask> _tasks = new List<BackgroundTask>();
26+
27+
public BackgroundTasksManager(ScriptingEngine engine)
28+
{
29+
_engine = engine;
30+
}
31+
32+
/// <summary>
33+
/// Создать и стартовать задание
34+
/// </summary>
35+
/// <param name="target">Объект, метод которого нужно выполнить</param>
36+
/// <param name="methodName">Имя экспортного метода в объекте</param>
37+
/// <param name="parameters">Массив параметров метода</param>
38+
/// <returns>ФоновоеЗадание</returns>
39+
[ContextMethod("Выполнить", "Execute")]
40+
public BackgroundTask Execute(IRuntimeContextInstance target, string methodName, ArrayImpl parameters = null)
41+
{
42+
var task = new BackgroundTask(target, methodName, parameters);
43+
_tasks.Add(task);
44+
45+
var worker = new Task(() =>
46+
{
47+
if(!MachineInstance.Current.IsRunning)
48+
_engine.Environment.LoadMemory(MachineInstance.Current);
49+
50+
task.ExecuteOnCurrentThread();
51+
52+
}, TaskCreationOptions.LongRunning);
53+
54+
task.WorkerTask = worker;
55+
worker.Start();
56+
57+
return task;
58+
}
59+
60+
[ContextMethod("Очистить", "Clear")]
61+
public void Clear()
62+
{
63+
_tasks.Clear();
64+
}
65+
66+
/// <summary>
67+
/// Ожидает завершения всех переданных заданий
68+
/// </summary>
69+
/// <param name="tasks">Массив заданий</param>
70+
/// <param name="timeout">Таймаут ожидания. 0 = ожидать бесконечно</param>
71+
/// <returns>Истина - дождались все задания, Ложь - истек таймаут</returns>
72+
[ContextMethod("ОжидатьВсе", "WaitAll")]
73+
public bool WaitAll(ArrayImpl tasks, int timeout = 0)
74+
{
75+
var workers = GetWorkerTasks(tasks);
76+
timeout = ConvertTimeout(timeout);
77+
78+
// Фоновые задания перехватывают исключения внутри себя
79+
// и выставляют свойство ИнформацияОбОшибке
80+
// если WaitAll выбросит исключение, значит действительно что-то пошло не так на уровне самого Task
81+
return Task.WaitAll(workers, timeout);
82+
}
83+
84+
/// <summary>
85+
/// Ожидать хотя бы одно из переданных заданий.
86+
/// </summary>
87+
/// <param name="tasks">Массив заданий</param>
88+
/// <param name="timeout">Таймаут ожидания. 0 = ожидать бесконечно</param>
89+
/// <returns>Число. Индекс в массиве заданий, указывающий на элемент-задание, которое завершилось. -1 = сработал таймаут</returns>
90+
[ContextMethod("ОжидатьЛюбое", "WaitAny")]
91+
public int WaitAny(ArrayImpl tasks, int timeout = 0)
92+
{
93+
var workers = GetWorkerTasks(tasks);
94+
timeout = ConvertTimeout(timeout);
95+
96+
// Фоновые задания перехватывают исключения внутри себя
97+
// и выставляют свойство ИнформацияОбОшибке
98+
// если WaitAny выбросит исключение, значит действительно что-то пошло не так на уровне самого Task
99+
return Task.WaitAny(workers, timeout);
100+
}
101+
102+
/// <summary>
103+
/// Блокирует поток до завершения всех заданий.
104+
/// Выбрасывает исключение, если какие-то задания завершились аварийно.
105+
/// Выброшенное исключение в свойстве Параметры содержит массив аварийных заданий.
106+
/// </summary>
107+
[ContextMethod("ОжидатьЗавершенияЗадач", "WaitCompletionOfTasks")]
108+
public void WaitCompletionOfTasks()
109+
{
110+
lock (_tasks)
111+
{
112+
var workers = GetWorkerTasks();
113+
Task.WaitAll(workers);
114+
115+
var failedTasks = _tasks.Where(x => x.State == TaskStateEnum.CompletedWithErrors)
116+
.ToList();
117+
118+
if (failedTasks.Any())
119+
{
120+
throw new ParametrizedRuntimeException(
121+
Locale.NStr("ru = 'Задания завершились с ошибками';en = 'Tasks are completed with errors'"),
122+
new ArrayImpl(failedTasks));
123+
}
124+
125+
_tasks.Clear();
126+
}
127+
}
128+
129+
[ContextMethod("ПолучитьФоновыеЗадания", "GetBackgroundJobs")]
130+
public ArrayImpl GetBackgroundJobs(StructureImpl filter = default)
131+
{
132+
if(filter == default)
133+
return new ArrayImpl(_tasks.ToArray());
134+
135+
var arr = new ArrayImpl();
136+
foreach (var task in _tasks)
137+
{
138+
var result = true;
139+
foreach (var filterItem in filter)
140+
{
141+
switch (filterItem.Key.AsString().ToLower())
142+
{
143+
case "состояние":
144+
case "state":
145+
var enumval = filterItem.Value as ClrEnumValueWrapper<TaskStateEnum>;
146+
if(enumval == default)
147+
continue;
148+
149+
result = result && task.State == enumval.UnderlyingValue;
150+
break;
151+
152+
case "имяметода":
153+
case "methodname":
154+
result = result && task.MethodName.ToLower() == filterItem.Value.AsString();
155+
break;
156+
157+
case "объект":
158+
case "object":
159+
result = result && task.Target.Equals(filterItem.Value);
160+
break;
161+
162+
case "уникальныйидентификатор":
163+
case "uuid":
164+
result = result && task.Identifier.Equals(filterItem.Value);
165+
break;
166+
}
167+
}
168+
169+
if(result)
170+
arr.Add(task);
171+
}
172+
173+
return arr;
174+
}
175+
176+
internal static int ConvertTimeout(int timeout)
177+
{
178+
if(timeout < 0)
179+
throw RuntimeException.InvalidArgumentValue();
180+
181+
return timeout == 0 ? Timeout.Infinite : timeout;
182+
}
183+
184+
private static Task[] GetWorkerTasks(ArrayImpl tasks)
185+
{
186+
return tasks
187+
.Cast<BackgroundTask>()
188+
.Select(x => x.WorkerTask)
189+
.ToArray();
190+
}
191+
192+
private static Task[] GetWorkerTasks(IEnumerable<BackgroundTask> tasks)
193+
{
194+
return tasks.Select(x => x.WorkerTask).ToArray();
195+
}
196+
197+
private Task[] GetWorkerTasks()
198+
{
199+
return GetWorkerTasks(_tasks);
200+
}
201+
202+
public void Dispose()
203+
{
204+
Task.WaitAll(GetWorkerTasks());
205+
_tasks.Clear();
206+
}
207+
}
208+
}

0 commit comments

Comments
 (0)