Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Operator Architecture Refactoring/HeuristicLab.Core/3.3/EngineBase.cs @ 2927

Last change on this file since 2927 was 2046, checked in by swagner, 15 years ago

Refactoring of the operator architecture (#95)

File size: 9.9 KB
Line 
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;
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  public abstract class EngineBase : ItemBase, IEngine {
36
37    /// <summary>
38    /// Field of the current instance that represent the operator graph.
39    /// </summary>
40    [Storable]
41    protected IOperatorGraph myOperatorGraph;
42    /// <summary>
43    /// Gets the current operator graph.
44    /// </summary>
45    public IOperatorGraph OperatorGraph {
46      get { return myOperatorGraph; }
47    }
48    /// <summary>
49    /// Field of the current instance that represent the global scope.
50    /// </summary>
51    [Storable]
52    protected IScope myGlobalScope;
53    /// <summary>
54    /// Gets the current global scope.
55    /// </summary>
56    public IScope GlobalScope {
57      get { return myGlobalScope; }
58    }
59
60    [Storable]
61    private TimeSpan myExecutionTime;
62    /// <summary>
63    /// Gets or sets the execution time.
64    /// </summary>
65    /// <remarks>Calls <see cref="OnExecutionTimeChanged"/> in the setter.</remarks>
66    public TimeSpan ExecutionTime {
67      get { return myExecutionTime; }
68      protected set {
69        myExecutionTime = value;
70        OnExecutionTimeChanged();
71      }
72    }
73
74    /// <summary>
75    /// Field of the current instance that represent the execution stack.
76    /// </summary>
77    [Storable]
78    protected Stack<IOperation> myExecutionStack;
79    /// <summary>
80    /// Gets the current execution stack.
81    /// </summary>
82    public Stack<IOperation> ExecutionStack {
83      get { return myExecutionStack; }
84    }
85
86    /// <summary>
87    /// Flag of the current instance whether it is currently running.
88    /// </summary>
89    protected bool myRunning;
90    /// <summary>
91    /// Gets information whether the instance is currently running.
92    /// </summary>
93    public bool Running {
94      get { return myRunning; }
95    }
96
97    /// <summary>
98    /// Flag of the current instance whether it is canceled.
99    /// </summary>
100    protected bool myCanceled;
101    /// <summary>
102    /// Gets information whether the instance is currently canceled.
103    /// </summary>
104    public bool Canceled {
105      get { return myCanceled; }
106    }
107    /// <summary>
108    /// Gets information whether the instance has already terminated.
109    /// </summary>
110    public virtual bool Terminated {
111      get { return ExecutionStack.Count == 0; }
112    }
113
114    /// <summary>
115    /// Initializes a new instance of <see cref="EngineBase"/> with a new global scope.
116    /// </summary>
117    /// <remarks>Calls <see cref="Reset"/>.</remarks>
118    protected EngineBase() {
119      myOperatorGraph = new OperatorGraph();
120      myGlobalScope = new Scope("Global");
121      myExecutionStack = new Stack<IOperation>();
122      Reset();
123    }
124
125    /// <summary>
126    /// Clones the current instance (deep clone).
127    /// </summary>
128    /// <remarks>Deep clone through <see cref="Auxiliary.Clone"/> method of helper class
129    /// <see cref="Auxiliary"/>.</remarks>
130    /// <param name="clonedObjects">Dictionary of all already clone objects. (Needed to avoid cycles.)</param>
131    /// <returns>The cloned object as <see cref="EngineBase"/>.</returns>
132    public override ICloneable Clone(ICloner cloner) {
133      EngineBase clone = (EngineBase)base.Clone(cloner);
134      clone.myOperatorGraph = (IOperatorGraph)cloner.Clone(OperatorGraph);
135      clone.myGlobalScope = (IScope)cloner.Clone(GlobalScope);
136      clone.myExecutionTime = ExecutionTime;
137      IOperation[] operations = new IOperation[ExecutionStack.Count];
138      ExecutionStack.CopyTo(operations, 0);
139      for (int i = operations.Length - 1; i >= 0; i--)
140        clone.myExecutionStack.Push((IOperation)cloner.Clone(operations[i]));
141      clone.myRunning = Running;
142      clone.myCanceled = Canceled;
143      return clone;
144    }
145
146    /// <inheritdoc/>
147    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
148    /// of class <see cref="ThreadPool"/>.</remarks>
149    public virtual void Execute() {
150      myRunning = true;
151      myCanceled = false;
152      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
153    }
154    /// <inheritdoc/>
155    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
156    /// of class <see cref="ThreadPool"/>.</remarks>
157    public virtual void ExecuteSteps(int steps) {
158      myRunning = true;
159      myCanceled = false;
160      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), steps);
161    }
162    /// <inheritdoc/>
163    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
164    /// of class <see cref="ThreadPool"/>.</remarks>
165    public void ExecuteStep() {
166      ExecuteSteps(1);
167    }
168    /// <inheritdoc/>
169    /// <remarks>Sets the protected flag <c>myCanceled</c> to <c>true</c>.</remarks>
170    public virtual void Abort() {
171      myCanceled = true;
172    }
173    /// <inheritdoc/>
174    /// <remarks>Sets <c>myCanceled</c> and <c>myRunning</c> to <c>false</c>. The global scope is cleared,
175    /// the execution time is reseted, the execution stack is cleared and a new <see cref="AtomicOperation"/>
176    /// with the initial operator is added. <br/>
177    /// Calls <see cref="OnInitialized"/>.</remarks>
178    public virtual void Reset() {
179      myCanceled = false;
180      myRunning = false;
181      GlobalScope.Clear();
182      ExecutionTime = new TimeSpan();
183      myExecutionStack.Clear();
184      if (OperatorGraph.InitialOperator != null)
185        myExecutionStack.Push(new AtomicOperation(OperatorGraph.InitialOperator, GlobalScope));
186      OnInitialized();
187    }
188
189    private void Run(object state) {
190      if (state == null) Run();
191      else RunSteps((int)state);
192      myRunning = false;
193      OnFinished();
194    }
195    private void Run() {
196      DateTime start = DateTime.Now;
197      DateTime end;
198      while ((!Canceled) && (!Terminated)) {
199        ProcessNextOperation();
200        end = DateTime.Now;
201        ExecutionTime += end - start;
202        start = end;
203      }
204      ExecutionTime += DateTime.Now - start;
205    }
206    private void RunSteps(int steps) {
207      DateTime start = DateTime.Now;
208      DateTime end;
209      int step = 0;
210      while ((!Canceled) && (!Terminated) && (step < steps)) {
211        ProcessNextOperation();
212        step++;
213        end = DateTime.Now;
214        ExecutionTime += end - start;
215        start = end;
216      }
217      ExecutionTime += DateTime.Now - start;
218    }
219
220    /// <summary>
221    /// Performs the next operation.
222    /// </summary>
223    protected abstract void ProcessNextOperation();
224
225    /// <summary>
226    /// Occurs when the current instance is initialized.
227    /// </summary>
228    public event EventHandler Initialized;
229    /// <summary>
230    /// Fires a new <c>Initialized</c> event.
231    /// </summary>
232    protected virtual void OnInitialized() {
233      if (Initialized != null)
234        Initialized(this, new EventArgs());
235    }
236    /// <summary>
237    /// Occurs when an operation is executed.
238    /// </summary>
239    public event EventHandler<EventArgs<IOperation>> OperationExecuted;
240    /// <summary>
241    /// Fires a new <c>OperationExecuted</c> event.
242    /// </summary>
243    /// <param name="operation">The operation that has been executed.</param>
244    protected virtual void OnOperationExecuted(IOperation operation) {
245      if (OperationExecuted != null)
246        OperationExecuted(this, new EventArgs<IOperation>(operation));
247    }
248    /// <summary>
249    /// Occurs when an exception occured during the execution.
250    /// </summary>
251    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
252    /// <summary>
253    /// Aborts the execution and fires a new <c>ExceptionOccurred</c> event.
254    /// </summary>
255    /// <param name="exception">The exception that was thrown.</param>
256    protected virtual void OnExceptionOccurred(Exception exception) {
257      Abort();
258      if (ExceptionOccurred != null)
259        ExceptionOccurred(this, new EventArgs<Exception>(exception));
260    }
261    /// <summary>
262    /// Occurs when the execution time changed.
263    /// </summary>
264    public event EventHandler ExecutionTimeChanged;
265    /// <summary>
266    /// Fires a new <c>ExecutionTimeChanged</c> event.
267    /// </summary>
268    protected virtual void OnExecutionTimeChanged() {
269      if (ExecutionTimeChanged != null)
270        ExecutionTimeChanged(this, new EventArgs());
271    }
272    /// <summary>
273    /// Occurs when the execution is finished.
274    /// </summary>
275    public event EventHandler Finished;
276    /// <summary>
277    /// Fires a new <c>Finished</c> event.
278    /// </summary>
279    protected virtual void OnFinished() {
280      if (Finished != null)
281        Finished(this, new EventArgs());
282    }
283  }
284}
Note: See TracBrowser for help on using the repository browser.