public async Task UpdateAsync(CilCompilation compilation, CancellationToken token) { try { var results = new List <NodePlugin.BuildResult>(FInstances.Length); foreach (var instance in FInstances) { var buildResult = await Task.Run(() => instance.Update(compilation), token); results.Add(buildResult); } token.ThrowIfCancellationRequested(); using (var swapper = new HotSwapper(Compilation, compilation, token)) { foreach (var result in results) { var instance = result.Plugin; if (!instance.IsDisposed) // It could be that the node has already been deleted { instance.SyncPinsAndRestoreState(result, swapper); } } ImplicitEntryPointInstanceManager.Update(swapper); Compilation = compilation; } } catch (OperationCanceledException) { // Fine } catch (Exception e) { LogAndStop(e); } }
// Called sequentially for all VL plugins on main thread public void SyncPinsAndRestoreState(BuildResult buildResult, HotSwapper swapper) { if (buildResult == FBuildResult) { return; // Same build result, nothing to do } if (buildResult == null) { return; // Something went seriously wrong during compile phase } if (buildResult.ClrMethodToCall == null) { FBuildResult = buildResult; return; // Something went wrong during compile phase } if (buildResult.Compilation.Age < FBuildResult.Compilation?.Age) { return; // Dismiss outdated builds } if (buildResult.ClrMethodToCall == FBuildResult.ClrMethodToCall) { // Same CLR method, nothing to do except for remember the new result // Holding on to the old would introduce a memory leak as old solutions and compilation could not get garbage collected FBuildResult = buildResult; return; } try { // Synchronize pins SyncPins(buildResult); // Restore the state if (FInstances.Length > 0) { var instanceType = buildResult.InstanceType; using (var reader = FInstances.GetReader()) using (var writer = FInstances.GetWriter()) { while (!reader.Eos) { var oldInstance = reader.Read(); if (oldInstance != null) { var newInstance = swapper.Swap(oldInstance, buildResult.Scope, buildResult.Factory); writer.Write(newInstance); } else { var newInstance = instanceType != null?buildResult.Factory.CreateInstance(instanceType, FInstanceId) : null; writer.Write(newInstance); } } } } } catch (Exception exception) { LogException(exception); throw; } finally { FBuildResult = buildResult; } }