Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/3.3/Engine.cs @ 2714

Last change on this file since 2714 was 2687, checked in by swagner, 15 years ago

Operator architecture refactoring (#95)

  • implemented ideas which came up during today's presentation of HeuristicLab.Core and related plugins
File size: 10.1 KB
RevLine 
[2]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25using System.Xml;
26using System.Threading;
[2653]27using System.Drawing;
[1823]28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[2474]29using HeuristicLab.Common;
[2]30
31namespace HeuristicLab.Core {
[776]32  /// <summary>
33  /// Base class to represent an engine, which is an interpreter, holding the code, the data and
34  /// the actual state, which is the runtime stack and a pointer onto the next operation. It represents
35  /// one execution and can handle parallel executions.
36  /// </summary>
[2664]37  [Item("Engine", "A base class for engines.")]
38  public abstract class Engine : Item, IEngine {
[2653]39    public override Image ItemImage {
40      get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Event; }
41    }
[1667]42
[776]43    /// <summary>
44    /// Field of the current instance that represent the operator graph.
45    /// </summary>
[2653]46    private OperatorGraph operatorGraph;
[776]47    /// <summary>
48    /// Gets the current operator graph.
49    /// </summary>
[2653]50    [Storable]
51    public OperatorGraph OperatorGraph {
52      get { return operatorGraph; }
53      set {
54        if (value == null) throw new ArgumentNullException();
55        if (value != operatorGraph) {
56          if (operatorGraph != null) operatorGraph.InitialOperatorChanged -= new EventHandler(operatorGraph_InitialOperatorChanged);
57          operatorGraph = value;
58          if (operatorGraph != null) operatorGraph.InitialOperatorChanged += new EventHandler(operatorGraph_InitialOperatorChanged);
59          OnOperatorGraphChanged();
60          Initialize();
61        }
62      }
[2]63    }
[2653]64
[776]65    /// <summary>
66    /// Field of the current instance that represent the global scope.
67    /// </summary>
[1667]68    [Storable]
[2653]69    private Scope globalScope;
[776]70    /// <summary>
71    /// Gets the current global scope.
72    /// </summary>
[2687]73    public IScope GlobalScope {
[2653]74      get { return globalScope; }
[2]75    }
76
[1667]77    [Storable]
[2653]78    private TimeSpan executionTime;
[776]79    /// <summary>
80    /// Gets or sets the execution time.
81    /// </summary>
82    /// <remarks>Calls <see cref="OnExecutionTimeChanged"/> in the setter.</remarks>
[2]83    public TimeSpan ExecutionTime {
[2653]84      get { return executionTime; }
[2]85      protected set {
[2653]86        executionTime = value;
[2]87        OnExecutionTimeChanged();
88      }
89    }
90
[776]91    /// <summary>
92    /// Field of the current instance that represent the execution stack.
93    /// </summary>
[1667]94    [Storable]
[2653]95    private Stack<ExecutionContext> executionStack;
[776]96    /// <summary>
97    /// Gets the current execution stack.
98    /// </summary>
[2653]99    protected Stack<ExecutionContext> ExecutionStack {
100      get { return executionStack; }
[2]101    }
[1667]102
[776]103    /// <summary>
104    /// Flag of the current instance whether it is currently running.
105    /// </summary>
[2653]106    private bool running;
[776]107    /// <summary>
108    /// Gets information whether the instance is currently running.
109    /// </summary>
[2]110    public bool Running {
[2653]111      get { return running; }
[2]112    }
[776]113
114    /// <summary>
115    /// Flag of the current instance whether it is canceled.
116    /// </summary>
[2653]117    private bool canceled;
[776]118    /// <summary>
119    /// Gets information whether the instance is currently canceled.
120    /// </summary>
[2653]121    protected bool Canceled {
122      get { return canceled; }
[2]123    }
[776]124    /// <summary>
125    /// Gets information whether the instance has already terminated.
126    /// </summary>
[2653]127    public bool Finished {
128      get { return executionStack.Count == 0; }
[2]129    }
130
[776]131    /// <summary>
132    /// Initializes a new instance of <see cref="EngineBase"/> with a new global scope.
133    /// </summary>
134    /// <remarks>Calls <see cref="Reset"/>.</remarks>
[2664]135    protected Engine() {
[2653]136      globalScope = new Scope("Global");
137      executionStack = new Stack<ExecutionContext>();
138      OperatorGraph = new OperatorGraph();
[2]139    }
140
[776]141    /// <summary>
142    /// Clones the current instance (deep clone).
143    /// </summary>
[2526]144    /// <remarks>Deep clone through <see cref="cloner.Clone"/> method of helper class
[776]145    /// <see cref="Auxiliary"/>.</remarks>
146    /// <param name="clonedObjects">Dictionary of all already clone objects. (Needed to avoid cycles.)</param>
147    /// <returns>The cloned object as <see cref="EngineBase"/>.</returns>
[2653]148    public override IDeepCloneable Clone(Cloner cloner) {
[2664]149      Engine clone = (Engine)base.Clone(cloner);
[2653]150      clone.OperatorGraph = (OperatorGraph)cloner.Clone(operatorGraph);
151      clone.globalScope = (Scope)cloner.Clone(globalScope);
152      clone.executionTime = executionTime;
153      ExecutionContext[] contexts = executionStack.ToArray();
154      for (int i = contexts.Length - 1; i >= 0; i--)
155        clone.executionStack.Push((ExecutionContext)cloner.Clone(contexts[i]));
156      clone.running = running;
157      clone.canceled = canceled;
[2]158      return clone;
159    }
160
[776]161    /// <inheritdoc/>
[2653]162    /// <remarks>Sets <c>myCanceled</c> and <c>myRunning</c> to <c>false</c>. The global scope is cleared,
163    /// the execution time is reseted, the execution stack is cleared and a new <see cref="AtomicOperation"/>
164    /// with the initial operator is added. <br/>
165    /// Calls <see cref="OnInitialized"/>.</remarks>
166    public void Initialize() {
167      canceled = false;
168      running = false;
[2687]169      globalScope.Clear();
[2653]170      ExecutionTime = new TimeSpan();
171      executionStack.Clear();
172      if (OperatorGraph.InitialOperator != null)
173        executionStack.Push(new ExecutionContext(null, OperatorGraph.InitialOperator, GlobalScope));
174      OnInitialized();
[2]175    }
[776]176    /// <inheritdoc/>
177    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
178    /// of class <see cref="ThreadPool"/>.</remarks>
[2653]179    public void Start() {
180      running = true;
181      canceled = false;
182      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
[2]183    }
[776]184    /// <inheritdoc/>
185    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
186    /// of class <see cref="ThreadPool"/>.</remarks>
[2653]187    public void Step() {
188      running = true;
189      canceled = false;
190      ThreadPool.QueueUserWorkItem(new WaitCallback(RunStep), null);
[2]191    }
[776]192    /// <inheritdoc/>
193    /// <remarks>Sets the protected flag <c>myCanceled</c> to <c>true</c>.</remarks>
[2653]194    public virtual void Stop() {
195      canceled = true;
[2]196    }
197
198    private void Run(object state) {
[2653]199      OnStarted();
[2]200      DateTime start = DateTime.Now;
201      DateTime end;
[2653]202      while ((!Canceled) && (!Finished)) {
203        ProcessNextOperator();
[2]204        end = DateTime.Now;
205        ExecutionTime += end - start;
206        start = end;
207      }
208      ExecutionTime += DateTime.Now - start;
[2653]209      running = false;
210      OnStopped();
[2]211    }
[2653]212    private void RunStep(object state) {
213      OnStarted();
[2]214      DateTime start = DateTime.Now;
[2653]215      if ((!Canceled) && (!Finished))
216        ProcessNextOperator();
[2]217      ExecutionTime += DateTime.Now - start;
[2653]218      running = false;
219      OnStopped();
[2]220    }
221
[776]222    /// <summary>
223    /// Performs the next operation.
224    /// </summary>
[2653]225    protected abstract void ProcessNextOperator();
[2]226
[2653]227    private void operatorGraph_InitialOperatorChanged(object sender, EventArgs e) {
228      Initialize();
229    }
230
231    public event EventHandler OperatorGraphChanged;
232    protected virtual void OnOperatorGraphChanged() {
233      if (OperatorGraphChanged != null)
234        OperatorGraphChanged(this, EventArgs.Empty);
235    }
[776]236    /// <summary>
[2653]237    /// Occurs when the execution time changed.
[776]238    /// </summary>
[2653]239    public event EventHandler ExecutionTimeChanged;
240    /// <summary>
241    /// Fires a new <c>ExecutionTimeChanged</c> event.
242    /// </summary>
243    protected virtual void OnExecutionTimeChanged() {
244      if (ExecutionTimeChanged != null)
245        ExecutionTimeChanged(this, new EventArgs());
246    }
247    /// <summary>
248    /// Occurs when the execution is initialized.
249    /// </summary>
[2]250    public event EventHandler Initialized;
[776]251    /// <summary>
252    /// Fires a new <c>Initialized</c> event.
253    /// </summary>
[2]254    protected virtual void OnInitialized() {
255      if (Initialized != null)
256        Initialized(this, new EventArgs());
257    }
[776]258    /// <summary>
[2653]259    /// Occurs when the execution is executed.
[776]260    /// </summary>
[2653]261    public event EventHandler Started;
[776]262    /// <summary>
[2653]263    /// Fires a new <c>Started</c> event.
[776]264    /// </summary>
[2653]265    protected virtual void OnStarted() {
266      if (Started != null)
267        Started(this, new EventArgs());
[2]268    }
[776]269    /// <summary>
[2653]270    /// Occurs when the execution is finished.
271    /// </summary>
272    public event EventHandler Stopped;
273    /// <summary>
274    /// Fires a new <c>Stopped</c> event.
275    /// </summary>
276    protected virtual void OnStopped() {
277      if (Stopped != null)
278        Stopped(this, new EventArgs());
279    }
280    /// <summary>
[776]281    /// Occurs when an exception occured during the execution.
282    /// </summary>
[2474]283    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
[776]284    /// <summary>
285    /// Aborts the execution and fires a new <c>ExceptionOccurred</c> event.
286    /// </summary>
287    /// <param name="exception">The exception that was thrown.</param>
[2]288    protected virtual void OnExceptionOccurred(Exception exception) {
289      if (ExceptionOccurred != null)
[2474]290        ExceptionOccurred(this, new EventArgs<Exception>(exception));
[2]291    }
292  }
293}
Note: See TracBrowser for help on using the repository browser.