public Task <CounterChangeInfo> GetCounterChangeAsync() { var callback = new MarshaledResultSetter <CounterChangeInfo>(); this.CoordinatorValue.NotifyOnCounterChange(callback); return(callback.Task); }
/// <summary> /// Ask the program to stop. /// </summary> public async Task Stop() { var callback = new MarshaledResultSetter(); _core.Stop(callback); await callback.Task; }
/// <summary> /// Invoke a public method accessible from outside of the interpreter (EXTERN FUNCTION). /// </summary> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="methodName">The name of the method.</param> /// <param name="awaitIfAsync">Await if the method is maked as asynchronous.</param> /// <param name="args">The arguments to pass to the method.</param> /// <returns>Returns the result of the invocation (a <see cref="Task"/> in the case of a not awaited asynchronous method, or the value returned by the method).</returns> public async Task <object> InvokeMethod(bool verbose, string methodName, bool awaitIfAsync, params object[] args) { var callback = new MarshaledResultSetter <object>(); _core.InvokeMethod(callback, verbose, methodName, awaitIfAsync, args); return(await callback.Task); }
/// <summary> /// Starts the interpreter in debug mode. The program will be interpreted and support the beakpoint and step by step debugging. /// </summary> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="args">The arguments to pass to the entry point.</param> /// <returns>Returns an awaitable task that can wait the end of the program execution</returns> public async Task StartDebugAsync(bool verbose, params object[] args) { var callback = new MarshaledResultSetter(); _core.StartDebug(callback, verbose, args); await callback.Task; }
/// <summary> /// Compiles the program in memory and load it or returns the build errors. /// </summary> /// <returns>Returns the build errors, or null if it succeed.</returns> public async Task <AggregateException> Build() { var callback = new MarshaledResultSetter <AggregateException>(); _core.Build(callback); return(await callback.Task); }
/// <summary> /// Compiles the program and save it on the hard drive or returns the build errors. /// </summary> /// <param name="outputType">Defines the type of assembly to generate.</param> /// <param name="outputPath">The full path to the .exe or .dll file to create if the build succeed.</param> /// <param name="assemblyName">(optional) Defines the name of the assembly to generate.</param> /// <param name="assemblyVersion">(optional) Defines the version of the assembly.</param> /// <param name="assemblyCopyright">(optional) Defines the copyright of the assembly.</param> /// <param name="releaseMode">(optional) Defines whether the compiler must build in release mode or debug mode.</param> /// <returns>Returns the build errors, or null if it succeed.</returns> public async Task <AggregateException> Build(BaZicCompilerOutputType outputType, string outputPath, string assemblyName = "", string assemblyVersion = "", string assemblyCopyright = "", bool releaseMode = false) { var callback = new MarshaledResultSetter <AggregateException>(); _core.Build(callback, outputType, outputPath, assemblyName, assemblyVersion, assemblyCopyright, releaseMode); return(await callback.Task); }
public void DoWork(MarshaledResultSetter <string> callback) { ThreadPool.QueueUserWorkItem(delegate { Thread.SpinWait(500000000); callback.SetResult(AppDomain.CurrentDomain.FriendlyName); }); }
static Task <string> DoWorkInOtherDomain(AppDomain ad) { var ch = new MarshaledResultSetter <string>(); Worker worker = (Worker)ad.CreateInstanceAndUnwrap(typeof(Worker).Assembly.FullName, typeof(Worker).FullName); worker.DoWork(ch); return(ch.Task); }
/// <summary> /// Ask the program to stop. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> internal void Stop(MarshaledResultSetter callback) { Requires.NotNull(_middleware, nameof(_middleware)); if (Verbose) { ChangeState(this, new BaZicInterpreterStateChangeEventArgs(L.BaZic.Runtime.BaZicInterpreter.StopRequested)); } Stop(true); callback.NotifyEndTask(); }
/// <summary> /// Initializes the start process for release and debug mode. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="action">The action to run in the flow.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="args">The arguments to pass to the entry point.</param> private void Start(MarshaledResultSetter callback, Action action, bool verbose, params object[] args) { CheckState(BaZicInterpreterState.Ready, BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Preparing)); _programArguments = args; Verbose = verbose; DebugInfos = null; Error = null; var currentCulture = LocalizationHelper.GetCurrentCulture(); _mainInterpreterTask = Task.Run(() => { _mainInterpreterThread = Thread.CurrentThread; LocalizationHelper.SetCurrentCulture(currentCulture, false, false); RuntimeHelpers.EnsureSufficientExecutionStack(); GCSettings.LatencyMode = GCLatencyMode.LowLatency; try { action(); } catch (Exception exception) { CoreHelper.ReportException(exception); if (!_ignoreException) { ChangeState(this, new UnexpectedException(exception)); } _ignoreException = false; } finally { GC.Collect(); GC.WaitForPendingFinalizers(); } }); _mainInterpreterTask.ContinueWith((task) => { callback.NotifyEndTask(); if (!_releaseModeForced) { RunningStateManager.UpdateState(); } _mainInterpreterThread = null; }); }
/// <summary> /// Starts the interpreter in release mode. The program will be compiled (emitted) and run quickly. Breakpoint statements will be ignored. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="args">The arguments to pass to the entry point.</param> /// <returns>Returns an awaitable task that can wait the end of the program execution</returns> internal void StartRelease(MarshaledResultSetter callback, bool verbose, params object[] args) { Requires.NotNull(_middleware, nameof(_middleware)); _releaseModeForced = true; _forceStop = false; DebugMode = false; var action = new Action(() => { if (_releaseModeRuntime == null || _compilerResult == null || _compilerResult.BuildErrors != null) { if (State == BaZicInterpreterState.Preparing) { _compilerResult = Build(BaZicCompilerOutputType.DynamicallyLinkedLibrary, string.Empty, string.Empty, string.Empty, false); if (_compilerResult.BuildErrors != null) { ChangeState(this, new UnexpectedException(_compilerResult.BuildErrors)); } else { _assemblySandbox.LoadAssembly(_compilerResult.Assembly, false); _compilerResult.Dispose(); } } } if (State == BaZicInterpreterState.Preparing) { RunningStateManager.SetIsRunningMainFunction(true); _releaseModeRuntime.Run(_programArguments); if (State == BaZicInterpreterState.Running || State == BaZicInterpreterState.Idle) { ProgramResult = _releaseModeRuntime.ProgramResult; RunningStateManager.UpdateState(); } } }); callback.ContinueWith(() => { RunningStateManager.SetIsRunningMainFunction(false); }, () => { RunningStateManager.UpdateState(); }); Start(callback, action, verbose, args); }
/// <summary> /// Invoke a public method accessible from outside of the interpreter (EXTERN FUNCTION). /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="methodName">The name of the method.</param> /// <param name="awaitIfAsync">Await if the method is maked as asynchronous.</param> /// <param name="args">The arguments to pass to the method.</param> /// <returns>Returns the result of the invocation (a <see cref="Task"/> in the case of a not awaited asynchronous method, or the value returned by the method).</returns> internal void InvokeMethod(MarshaledResultSetter <object> callback, bool verbose, string methodName, bool awaitIfAsync, object[] args) { Requires.NotNull(_middleware, nameof(_middleware)); Error = null; _forceStop = false; if (_releaseModeForced) { InvokeMethodRelease(callback, verbose, methodName, awaitIfAsync, args); } else { InvokeMethodDebug(callback, verbose, methodName, awaitIfAsync, args); } }
public void NotifyOnCounterChange(MarshaledResultSetter<CounterChangeInfo> callback) { Task.WhenAny(this.counters.Select(c => c.ReceiveAsync())) .ContinueWith(delegate { callback.SetResult(new CounterChangeInfo { NewValues = this.counters .Select(c => new { c.Key, Result = c.ReturnAndFlushIfReceived() }) .Where(x => x.Result != null) .Select(x => new KeyValuePair<string, int>(x.Key, x.Result.Value)) .ToList() }); }); }
/// <summary> /// Starts the interpreter in debug mode. The program will be interpreted and support the beakpoint and step by step debugging. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="args">The arguments to pass to the entry point.</param> /// <returns>Returns an awaitable task that can wait the end of the program execution</returns> internal void StartDebug(MarshaledResultSetter callback, bool verbose, params object[] args) { Requires.NotNull(_middleware, nameof(_middleware)); if (_releaseModeForced) { throw new UnexpectedException(new Exception(L.BaZic.Runtime.BaZicInterpreter.CannotStartDebugAfterBuild)); } _forceStop = false; DebugMode = true; var action = new Action(() => { LoadAssemblies(); if (State == BaZicInterpreterState.Preparing) { if (ProgramInterpreter == null) { var executionFlowId = RunningStateManager.AddCallStackForUnwaitedMethodInvocation(); RunningStateManager.SetIsRunningMainFunction(true); ProgramInterpreter = new ProgramInterpreter(this, Program, executionFlowId); } ProgramInterpreter.Start(_programArguments); RunningStateManager.WaitUnwaitedMethodInvocation(ProgramInterpreter.ExecutionFlowId); if (State == BaZicInterpreterState.Running || State == BaZicInterpreterState.Idle) { ProgramResult = ProgramInterpreter.ProgramResult; FreePauseModeWaiter(); } } }); callback.ContinueWith(() => { RunningStateManager.SetIsRunningMainFunction(false); RunningStateManager.UpdateState(); }, null); Start(callback, action, verbose, args); }
/// <summary> /// Compiles the program in memory and load it (to use it later) or returns the build errors. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <returns>Returns the build errors, or null if it succeed.</returns> internal void Build(MarshaledResultSetter <AggregateException> callback) { Requires.NotNull(_middleware, nameof(_middleware)); if (DebugMode) { throw new UnexpectedException(new Exception(L.BaZic.Runtime.BaZicInterpreter.CannotBuildAfterStartDebug)); } CheckState(BaZicInterpreterState.Ready, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); if (ProgramIsOptimized) { throw new InvalidOperationException(L.BaZic.Runtime.BaZicInterpreter.CannotRunOptimizedProgramInRelease); } Error = null; ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); AggregateException buildErrors = null; var currentCulture = LocalizationHelper.GetCurrentCulture(); _mainInterpreterTask = Task.Run(() => { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); _compilerResult = Build(BaZicCompilerOutputType.DynamicallyLinkedLibrary, string.Empty, string.Empty, string.Empty, false); if (_compilerResult.BuildErrors != null) { buildErrors = _compilerResult.BuildErrors; ChangeState(this, new UnexpectedException(_compilerResult.BuildErrors)); } else { _assemblySandbox.LoadAssembly(_compilerResult.Assembly, false); _compilerResult.Dispose(); _releaseModeForced = true; ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Stopped)); } }); _mainInterpreterTask.ContinueWith((task) => { callback.SetResult(buildErrors); }); }
/// <summary> /// Compiles the program in memory and save it on the hard drive or returns the build errors. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="outputType">Defines the type of assembly to generate</param> /// <param name="outputPath">The full path to the .exe or .dll file to create if the build succeed.</param> /// <param name="assemblyName">Defines the name of the assembly to generate.</param> /// <param name="assemblyVersion">Defines the version of the assembly.</param> /// <param name="assemblyCopyright">Defines the copyright of the assembly.</param> /// <param name="releaseMode">Defines whether the compiler must build in release mode or debug mode.</param> /// <returns>Returns the build errors, or null if it succeed.</returns> internal void Build(MarshaledResultSetter <AggregateException> callback, BaZicCompilerOutputType outputType, string outputPath, string assemblyName, string assemblyVersion, string assemblyCopyright, bool releaseMode) { Requires.NotNull(_middleware, nameof(_middleware)); Requires.NotNullOrWhiteSpace(outputPath, nameof(outputPath)); if (DebugMode) { throw new UnexpectedException(new Exception(L.BaZic.Runtime.BaZicInterpreter.CannotBuildAfterStartDebug)); } CheckState(BaZicInterpreterState.Ready, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); if (ProgramIsOptimized) { throw new InvalidOperationException(L.BaZic.Runtime.BaZicInterpreter.CannotRunOptimizedProgramInRelease); } Error = null; ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); AggregateException buildErrors = null; var currentCulture = LocalizationHelper.GetCurrentCulture(); _mainInterpreterTask = Task.Run(() => { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); var outputFile = new FileInfo(outputPath); var directory = outputFile.Directory; if (string.IsNullOrWhiteSpace(outputFile.Extension)) { if (outputType == BaZicCompilerOutputType.DynamicallyLinkedLibrary) { outputFile = new FileInfo(outputPath + ".dll"); } else { outputFile = new FileInfo(outputPath + ".exe"); } } var outputFileName = Path.GetFileNameWithoutExtension(outputPath); var outputPdbFile = new FileInfo(Path.Combine(directory.FullName, outputFileName + ".pdb")); using (var compileResult = Build(outputType, assemblyName, assemblyVersion, assemblyCopyright, releaseMode)) { if (compileResult.BuildErrors != null) { buildErrors = compileResult.BuildErrors; ChangeState(this, new UnexpectedException(buildErrors)); return; } try { if (!directory.Exists) { directory.Create(); } var assembliesToCopy = _assemblySandbox.GetAssemblies().Where(a => a.CopyToLocal).Concat(Program.Assemblies.Where(a => a.CopyToLocal)).Distinct(); foreach (var assembly in assembliesToCopy) { if (File.Exists(assembly.Location)) { File.Copy(assembly.Location, Path.Combine(directory.FullName, Path.GetFileName(assembly.Location))); var pdbFilePath = Path.Combine(Directory.GetParent(assembly.Location).FullName, Path.GetFileNameWithoutExtension(assembly.Location) + ".pdb"); var xmlFilePath = Path.Combine(Directory.GetParent(assembly.Location).FullName, Path.GetFileNameWithoutExtension(assembly.Location) + ".xml"); if (File.Exists(pdbFilePath)) { File.Copy(pdbFilePath, Path.Combine(directory.FullName, Path.GetFileName(pdbFilePath))); } if (File.Exists(xmlFilePath)) { File.Copy(xmlFilePath, Path.Combine(directory.FullName, Path.GetFileName(xmlFilePath))); } } } using (var assemblyFileStream = new FileStream(outputFile.FullName, FileMode.Create)) using (var pdbFileStream = new FileStream(outputPdbFile.FullName, FileMode.Create)) { compileResult.Assembly.WriteTo(assemblyFileStream); compileResult.Pdb.WriteTo(pdbFileStream); } ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Stopped)); } catch (Exception exception) { CoreHelper.ReportException(exception); buildErrors = new AggregateException(new List <Exception> { exception }); ChangeState(this, new UnexpectedException(exception)); } } }); _mainInterpreterTask.ContinueWith((task) => { callback.SetResult(buildErrors); }); }
/// <summary> /// Invoke a public method accessible from outside of the interpreter (EXTERN FUNCTION) in Debug mode. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="methodName">The name of the method.</param> /// <param name="awaitIfAsync">Await if the method is maked as asynchronous.</param> /// <param name="args">The arguments to pass to the method.</param> /// <returns>Returns the result of the invocation (a <see cref="Task"/> in the case of a not awaited asynchronous method, or the value returned by the method).</returns> private async void InvokeMethodDebug(MarshaledResultSetter <object> callback, bool verbose, string methodName, bool awaitIfAsync, object[] args) { DebugMode = true; if (State == BaZicInterpreterState.Ready || State == BaZicInterpreterState.Stopped || State == BaZicInterpreterState.StoppedWithError) { // Creates a new ProgramInterpreter. var privateCallback = new MarshaledResultSetter(); var action = new Action(() => { LoadAssemblies(); if (State == BaZicInterpreterState.Preparing) { var executionFlowIdProgram = RunningStateManager.AddCallStackForUnwaitedMethodInvocation(); ProgramInterpreter = new ProgramInterpreter(this, Program, executionFlowIdProgram); ProgramInterpreter.InitializeGlobalState(); ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Idle)); } }); Start(privateCallback, action, verbose); await privateCallback.Task; } var currentCulture = LocalizationHelper.GetCurrentCulture(); var thread = Task.Run(() => { object result = null; try { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); Task.Delay(500).ConfigureAwait(false).GetAwaiter().GetResult(); if (State == BaZicInterpreterState.Preparing) { // Wait for running. WaitForState(BaZicInterpreterState.Running, BaZicInterpreterState.Idle); } if (State == BaZicInterpreterState.Running) { // Wait for having being idle. WaitForState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); if (_forceStop) { // The state is Stopped and it has been requested by the user (command await Stop()) or the interpreter is disposing. return(null); } } CheckState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); var arguments = new List <PrimitiveExpression>(); if (args != null) { foreach (var argument in args) { arguments.Add(new PrimitiveExpression(argument)); } } RunningStateManager.StartsExternMethod(); var executionFlowId = RunningStateManager.AddCallStackForUnwaitedMethodInvocation(); result = ProgramInterpreter.InvokeMethod(executionFlowId, methodName, awaitIfAsync, arguments.ToArray()); } catch (Exception exception) { CoreHelper.ReportException(exception); if (!_ignoreException) { ChangeState(this, new UnexpectedException(exception)); } _ignoreException = false; } finally { RunningStateManager.StopsExternMethod(); RunningStateManager.UpdateState(); GC.Collect(); GC.WaitForPendingFinalizers(); } return(result); }); var t = thread.ContinueWith((task) => { callback.SetResult(task.Result); }); }
/// <summary> /// Invoke a public method accessible from outside of the interpreter (EXTERN FUNCTION) in Release mode. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="methodName">The name of the method.</param> /// <param name="awaitIfAsync">Await if the method is maked as asynchronous.</param> /// <param name="args">The arguments to pass to the method.</param> /// <returns>Returns the result of the invocation (a <see cref="Task"/> in the case of a not awaited asynchronous method, or the value returned by the method).</returns> private void InvokeMethodRelease(MarshaledResultSetter <object> callback, bool verbose, string methodName, bool awaitIfAsync, object[] args) { var currentCulture = LocalizationHelper.GetCurrentCulture(); var thread = Task.Run(() => { if (State == BaZicInterpreterState.Preparing) { // Wait for running. WaitForState(BaZicInterpreterState.Running, BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); } if (State == BaZicInterpreterState.Running) { // Wait for having being idle. WaitForState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); } if (_forceStop) { // The state is Stopped and it has been requested by the user (command await Stop()) or the interpreter is disposing. return(null); } CheckState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); RunningStateManager.StartsExternMethod(); object result = null; ThreadHelper.RunOnStaThread(() => { try { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); if (Verbose) { ChangeState(this, new BaZicInterpreterStateChangeEventArgs(L.BaZic.Runtime.CompiledProgramRunner.FormattedInvokeMethod(methodName))); } result = _releaseModeRuntime.InvokeMethod(methodName, args); if (result != null && result is Task && awaitIfAsync) { var task = (Task)result; task.ConfigureAwait(false).GetAwaiter().GetResult(); if (result.GetType().IsGenericType) { result = ((dynamic)task).Result; } else { result = null; }; } } catch (Exception exception) { CoreHelper.ReportException(exception); if (!_ignoreException) { ChangeState(this, new UnexpectedException(exception)); } _ignoreException = false; } finally { GC.Collect(); GC.WaitForPendingFinalizers(); } }); return(result); }); var t = thread.ContinueWith((task) => { RunningStateManager.StopsExternMethod(); RunningStateManager.UpdateState(); callback.SetResult(task.Result); }); }
public Task<CounterChangeInfo> GetCounterChangeAsync() { var callback = new MarshaledResultSetter<CounterChangeInfo>(); this.CoordinatorValue.NotifyOnCounterChange(callback); return callback.Task; }