Free cookie consent management tool by TermsFeed Policy Generator

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

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

Operator architecture refactoring (#95)

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