Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 2790 was 2790, checked in by swagner, 14 years ago

Operator architecture refactoring (#95)

  • implemented reviewers' comments
  • added additional plugins HeuristicLab.Evolutionary, HeuristicLab.Permutation, HeuristicLab.Selection, and HeuristicLab.Routing.TSP
File size: 10.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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;
27using System.Drawing;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29using HeuristicLab.Common;
30
31namespace HeuristicLab.Core {
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>
37  [Item("Engine", "A base class for engines.")]
38  public abstract class Engine : Item, IEngine {
39    public override Image ItemImage {
40      get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Event; }
41    }
42
43    /// <summary>
44    /// Field of the current instance that represent the operator graph.
45    /// </summary>
46    private OperatorGraph operatorGraph;
47    /// <summary>
48    /// Gets the current operator graph.
49    /// </summary>
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          Prepare();
61        }
62      }
63    }
64
65    /// <summary>
66    /// Field of the current instance that represent the global scope.
67    /// </summary>
68    [Storable]
69    private IScope globalScope;
70    /// <summary>
71    /// Gets the current global scope.
72    /// </summary>
73    public IScope GlobalScope {
74      get { return globalScope; }
75    }
76
77    [Storable]
78    private TimeSpan executionTime;
79    /// <summary>
80    /// Gets or sets the execution time.
81    /// </summary>
82    /// <remarks>Calls <see cref="OnExecutionTimeChanged"/> in the setter.</remarks>
83    public TimeSpan ExecutionTime {
84      get { return executionTime; }
85      protected set {
86        executionTime = value;
87        OnExecutionTimeChanged();
88      }
89    }
90
91    /// <summary>
92    /// Field of the current instance that represent the execution stack.
93    /// </summary>
94    [Storable]
95    private Stack<IExecutionSequence> executionStack;
96    /// <summary>
97    /// Gets the current execution stack.
98    /// </summary>
99    protected Stack<IExecutionSequence> ExecutionStack {
100      get { return executionStack; }
101    }
102
103    /// <summary>
104    /// Flag of the current instance whether it is currently running.
105    /// </summary>
106    private bool running;
107    /// <summary>
108    /// Gets information whether the instance is currently running.
109    /// </summary>
110    public bool Running {
111      get { return running; }
112    }
113
114    /// <summary>
115    /// Flag of the current instance whether it is canceled.
116    /// </summary>
117    private bool canceled;
118    /// <summary>
119    /// Gets information whether the instance is currently canceled.
120    /// </summary>
121    protected bool Canceled {
122      get { return canceled; }
123    }
124    /// <summary>
125    /// Gets information whether the instance has already terminated.
126    /// </summary>
127    public bool Finished {
128      get { return executionStack.Count == 0; }
129    }
130
131    /// <summary>
132    /// Initializes a new instance of <see cref="EngineBase"/> with a new global scope.
133    /// </summary>
134    protected Engine() {
135      globalScope = new Scope("Global");
136      executionStack = new Stack<IExecutionSequence>();
137      OperatorGraph = new OperatorGraph();
138    }
139
140    /// <summary>
141    /// Clones the current instance (deep clone).
142    /// </summary>
143    /// <remarks>Deep clone through <see cref="cloner.Clone"/> method of helper class
144    /// <see cref="Auxiliary"/>.</remarks>
145    /// <param name="clonedObjects">Dictionary of all already clone objects. (Needed to avoid cycles.)</param>
146    /// <returns>The cloned object as <see cref="EngineBase"/>.</returns>
147    public override IDeepCloneable Clone(Cloner cloner) {
148      Engine clone = (Engine)base.Clone(cloner);
149      clone.OperatorGraph = (OperatorGraph)cloner.Clone(operatorGraph);
150      clone.globalScope = (Scope)cloner.Clone(globalScope);
151      clone.executionTime = executionTime;
152      IExecutionSequence[] contexts = executionStack.ToArray();
153      for (int i = contexts.Length - 1; i >= 0; i--)
154        clone.executionStack.Push((IExecutionSequence)cloner.Clone(contexts[i]));
155      clone.running = running;
156      clone.canceled = canceled;
157      return clone;
158    }
159
160    /// <inheritdoc/>
161    /// <remarks>Sets <c>myCanceled</c> and <c>myRunning</c> to <c>false</c>. The global scope is cleared,
162    /// the execution time is reset, the execution stack is cleared and a new <see cref="AtomicOperation"/>
163    /// with the initial operator is added. <br/>
164    /// Calls <see cref="OnPrepared"/>.</remarks>
165    public void Prepare() {
166      canceled = false;
167      running = false;
168      globalScope.Clear();
169      ExecutionTime = new TimeSpan();
170      executionStack.Clear();
171      if (OperatorGraph.InitialOperator != null)
172        executionStack.Push(new ExecutionContext(null, OperatorGraph.InitialOperator, GlobalScope));
173      OnPrepared();
174    }
175    /// <inheritdoc/>
176    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
177    /// of class <see cref="ThreadPool"/>.</remarks>
178    public void Start() {
179      running = true;
180      canceled = false;
181      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
182    }
183    /// <inheritdoc/>
184    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
185    /// of class <see cref="ThreadPool"/>.</remarks>
186    public void Step() {
187      running = true;
188      canceled = false;
189      ThreadPool.QueueUserWorkItem(new WaitCallback(RunStep), null);
190    }
191    /// <inheritdoc/>
192    /// <remarks>Sets the protected flag <c>myCanceled</c> to <c>true</c>.</remarks>
193    public virtual void Stop() {
194      canceled = true;
195    }
196
197    private void Run(object state) {
198      OnStarted();
199      DateTime start = DateTime.Now;
200      DateTime end;
201      while ((!Canceled) && (!Finished)) {
202        ProcessNextOperator();
203        end = DateTime.Now;
204        ExecutionTime += end - start;
205        start = end;
206      }
207      ExecutionTime += DateTime.Now - start;
208      running = false;
209      OnStopped();
210    }
211    private void RunStep(object state) {
212      OnStarted();
213      DateTime start = DateTime.Now;
214      if ((!Canceled) && (!Finished))
215        ProcessNextOperator();
216      ExecutionTime += DateTime.Now - start;
217      running = false;
218      OnStopped();
219    }
220
221    /// <summary>
222    /// Performs the next operation.
223    /// </summary>
224    protected abstract void ProcessNextOperator();
225
226    private void operatorGraph_InitialOperatorChanged(object sender, EventArgs e) {
227      Prepare();
228    }
229
230    public event EventHandler OperatorGraphChanged;
231    protected virtual void OnOperatorGraphChanged() {
232      if (OperatorGraphChanged != null)
233        OperatorGraphChanged(this, EventArgs.Empty);
234    }
235    /// <summary>
236    /// Occurs when the execution time changed.
237    /// </summary>
238    public event EventHandler ExecutionTimeChanged;
239    /// <summary>
240    /// Fires a new <c>ExecutionTimeChanged</c> event.
241    /// </summary>
242    protected virtual void OnExecutionTimeChanged() {
243      if (ExecutionTimeChanged != null)
244        ExecutionTimeChanged(this, new EventArgs());
245    }
246    /// <summary>
247    /// Occurs when the execution is prepared for a new run.
248    /// </summary>
249    public event EventHandler Prepared;
250    /// <summary>
251    /// Fires a new <c>Prepared</c> event.
252    /// </summary>
253    protected virtual void OnPrepared() {
254      if (Prepared != null)
255        Prepared(this, new EventArgs());
256    }
257    /// <summary>
258    /// Occurs when the execution is executed.
259    /// </summary>
260    public event EventHandler Started;
261    /// <summary>
262    /// Fires a new <c>Started</c> event.
263    /// </summary>
264    protected virtual void OnStarted() {
265      if (Started != null)
266        Started(this, new EventArgs());
267    }
268    /// <summary>
269    /// Occurs when the execution is finished.
270    /// </summary>
271    public event EventHandler Stopped;
272    /// <summary>
273    /// Fires a new <c>Stopped</c> event.
274    /// </summary>
275    protected virtual void OnStopped() {
276      if (Stopped != null)
277        Stopped(this, new EventArgs());
278    }
279    /// <summary>
280    /// Occurs when an exception occured during the execution.
281    /// </summary>
282    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
283    /// <summary>
284    /// Aborts the execution and fires a new <c>ExceptionOccurred</c> event.
285    /// </summary>
286    /// <param name="exception">The exception that was thrown.</param>
287    protected virtual void OnExceptionOccurred(Exception exception) {
288      if (ExceptionOccurred != null)
289        ExceptionOccurred(this, new EventArgs<Exception>(exception));
290    }
291  }
292}
Note: See TracBrowser for help on using the repository browser.