Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/3.3/EngineBase.cs @ 2660

Last change on this file since 2660 was 2653, checked in by swagner, 15 years ago

Committing first results of the refactoring of HeuristicLab.Core and related plugins (#95)

File size: 10.1 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 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("EngineBase", "A base class for engines.")]
38  public abstract class EngineBase : ItemBase, 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          Initialize();
61        }
62      }
63    }
64
65    /// <summary>
66    /// Field of the current instance that represent the global scope.
67    /// </summary>
68    [Storable]
69    private Scope globalScope;
70    /// <summary>
71    /// Gets the current global scope.
72    /// </summary>
73    public Scope 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<ExecutionContext> executionStack;
96    /// <summary>
97    /// Gets the current execution stack.
98    /// </summary>
99    protected Stack<ExecutionContext> 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    /// <remarks>Calls <see cref="Reset"/>.</remarks>
135    protected EngineBase() {
136      globalScope = new Scope("Global");
137      executionStack = new Stack<ExecutionContext>();
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      EngineBase clone = (EngineBase)base.Clone(cloner);
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;
158      return clone;
159    }
160
161    /// <inheritdoc/>
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;
169      GlobalScope.Clear();
170      ExecutionTime = new TimeSpan();
171      executionStack.Clear();
172      if (OperatorGraph.InitialOperator != null)
173        executionStack.Push(new ExecutionContext(null, OperatorGraph.InitialOperator, GlobalScope));
174      OnInitialized();
175    }
176    /// <inheritdoc/>
177    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
178    /// of class <see cref="ThreadPool"/>.</remarks>
179    public void Start() {
180      running = true;
181      canceled = false;
182      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
183    }
184    /// <inheritdoc/>
185    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
186    /// of class <see cref="ThreadPool"/>.</remarks>
187    public void Step() {
188      running = true;
189      canceled = false;
190      ThreadPool.QueueUserWorkItem(new WaitCallback(RunStep), null);
191    }
192    /// <inheritdoc/>
193    /// <remarks>Sets the protected flag <c>myCanceled</c> to <c>true</c>.</remarks>
194    public virtual void Stop() {
195      canceled = true;
196    }
197
198    private void Run(object state) {
199      OnStarted();
200      DateTime start = DateTime.Now;
201      DateTime end;
202      while ((!Canceled) && (!Finished)) {
203        ProcessNextOperator();
204        end = DateTime.Now;
205        ExecutionTime += end - start;
206        start = end;
207      }
208      ExecutionTime += DateTime.Now - start;
209      running = false;
210      OnStopped();
211    }
212    private void RunStep(object state) {
213      OnStarted();
214      DateTime start = DateTime.Now;
215      if ((!Canceled) && (!Finished))
216        ProcessNextOperator();
217      ExecutionTime += DateTime.Now - start;
218      running = false;
219      OnStopped();
220    }
221
222    /// <summary>
223    /// Performs the next operation.
224    /// </summary>
225    protected abstract void ProcessNextOperator();
226
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    }
236    /// <summary>
237    /// Occurs when the execution time changed.
238    /// </summary>
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>
250    public event EventHandler Initialized;
251    /// <summary>
252    /// Fires a new <c>Initialized</c> event.
253    /// </summary>
254    protected virtual void OnInitialized() {
255      if (Initialized != null)
256        Initialized(this, new EventArgs());
257    }
258    /// <summary>
259    /// Occurs when the execution is executed.
260    /// </summary>
261    public event EventHandler Started;
262    /// <summary>
263    /// Fires a new <c>Started</c> event.
264    /// </summary>
265    protected virtual void OnStarted() {
266      if (Started != null)
267        Started(this, new EventArgs());
268    }
269    /// <summary>
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>
281    /// Occurs when an exception occured during the execution.
282    /// </summary>
283    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
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>
288    protected virtual void OnExceptionOccurred(Exception exception) {
289      if (ExceptionOccurred != null)
290        ExceptionOccurred(this, new EventArgs<Exception>(exception));
291    }
292  }
293}
Note: See TracBrowser for help on using the repository browser.