Free cookie consent management tool by TermsFeed Policy Generator

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

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

Operator architecture refactoring (#95)

  • worked on algorithms
File size: 10.4 KB
RevLine 
[2]1#region License Information
2/* HeuristicLab
[2790]3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[2]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;
[2796]24using System.Drawing;
[2]25using System.Threading;
[2796]26using HeuristicLab.Common;
[1823]27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[2]28
29namespace HeuristicLab.Core {
[776]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>
[2664]35  [Item("Engine", "A base class for engines.")]
36  public abstract class Engine : Item, IEngine {
[2653]37    public override Image ItemImage {
38      get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Event; }
39    }
[1667]40
[2653]41    private OperatorGraph operatorGraph;
[776]42    /// <summary>
[2796]43    /// Gets or sets the current operator graph.
[776]44    /// </summary>
[2653]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();
[2790]55          Prepare();
[2653]56        }
57      }
[2]58    }
[2653]59
[776]60    /// <summary>
61    /// Field of the current instance that represent the global scope.
62    /// </summary>
[1667]63    [Storable]
[2790]64    private IScope globalScope;
[776]65    /// <summary>
66    /// Gets the current global scope.
67    /// </summary>
[2687]68    public IScope GlobalScope {
[2653]69      get { return globalScope; }
[2]70    }
71
[1667]72    [Storable]
[2653]73    private TimeSpan executionTime;
[776]74    /// <summary>
75    /// Gets or sets the execution time.
76    /// </summary>
77    /// <remarks>Calls <see cref="OnExecutionTimeChanged"/> in the setter.</remarks>
[2]78    public TimeSpan ExecutionTime {
[2653]79      get { return executionTime; }
[2]80      protected set {
[2653]81        executionTime = value;
[2]82        OnExecutionTimeChanged();
83      }
84    }
85
[776]86    /// <summary>
87    /// Field of the current instance that represent the execution stack.
88    /// </summary>
[1667]89    [Storable]
[2834]90    private Stack<IOperation> executionStack;
[776]91    /// <summary>
92    /// Gets the current execution stack.
93    /// </summary>
[2834]94    protected Stack<IOperation> ExecutionStack {
[2653]95      get { return executionStack; }
[2]96    }
[1667]97
[776]98    /// <summary>
99    /// Flag of the current instance whether it is currently running.
100    /// </summary>
[2653]101    private bool running;
[776]102    /// <summary>
103    /// Gets information whether the instance is currently running.
104    /// </summary>
[2]105    public bool Running {
[2653]106      get { return running; }
[2]107    }
[776]108
109    /// <summary>
110    /// Flag of the current instance whether it is canceled.
111    /// </summary>
[2653]112    private bool canceled;
[776]113    /// <summary>
114    /// Gets information whether the instance is currently canceled.
115    /// </summary>
[2653]116    protected bool Canceled {
117      get { return canceled; }
[2851]118      private set {
119        if (canceled != value) {
120          canceled = value;
121          OnCanceledChanged();
122        }
123      }
[2]124    }
[776]125    /// <summary>
126    /// Gets information whether the instance has already terminated.
127    /// </summary>
[2653]128    public bool Finished {
129      get { return executionStack.Count == 0; }
[2]130    }
131
[776]132    /// <summary>
133    /// Initializes a new instance of <see cref="EngineBase"/> with a new global scope.
134    /// </summary>
[2664]135    protected Engine() {
[2653]136      globalScope = new Scope("Global");
[2834]137      executionStack = new Stack<IOperation>();
[2653]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;
[2834]153      IOperation[] contexts = executionStack.ToArray();
[2653]154      for (int i = contexts.Length - 1; i >= 0; i--)
[2834]155        clone.executionStack.Push((IOperation)cloner.Clone(contexts[i]));
[2653]156      clone.running = running;
157      clone.canceled = canceled;
[2]158      return clone;
159    }
160
[2834]161    public void Prepare(IOperation initialOperation) {
[2851]162      Canceled = false;
[2653]163      running = false;
[2687]164      globalScope.Clear();
[2653]165      ExecutionTime = new TimeSpan();
166      executionStack.Clear();
[2834]167      if (initialOperation != null)
168        executionStack.Push(initialOperation);
[2790]169      OnPrepared();
[2]170    }
[776]171    /// <inheritdoc/>
[2834]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/>
[776]181    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
182    /// of class <see cref="ThreadPool"/>.</remarks>
[2653]183    public void Start() {
184      running = true;
[2851]185      Canceled = false;
[2653]186      ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null);
[2]187    }
[776]188    /// <inheritdoc/>
189    /// <remarks>Calls <see cref="ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, object)"/>
190    /// of class <see cref="ThreadPool"/>.</remarks>
[2653]191    public void Step() {
192      running = true;
[2851]193      Canceled = false;
[2653]194      ThreadPool.QueueUserWorkItem(new WaitCallback(RunStep), null);
[2]195    }
[776]196    /// <inheritdoc/>
197    /// <remarks>Sets the protected flag <c>myCanceled</c> to <c>true</c>.</remarks>
[2851]198    public void Stop() {
199      Canceled = true;
[2]200    }
201
202    private void Run(object state) {
[2653]203      OnStarted();
[2]204      DateTime start = DateTime.Now;
205      DateTime end;
[2653]206      while ((!Canceled) && (!Finished)) {
207        ProcessNextOperator();
[2]208        end = DateTime.Now;
209        ExecutionTime += end - start;
210        start = end;
211      }
212      ExecutionTime += DateTime.Now - start;
[2653]213      running = false;
214      OnStopped();
[2]215    }
[2653]216    private void RunStep(object state) {
217      OnStarted();
[2]218      DateTime start = DateTime.Now;
[2653]219      if ((!Canceled) && (!Finished))
220        ProcessNextOperator();
[2]221      ExecutionTime += DateTime.Now - start;
[2653]222      running = false;
223      OnStopped();
[2]224    }
225
[776]226    /// <summary>
227    /// Performs the next operation.
228    /// </summary>
[2653]229    protected abstract void ProcessNextOperator();
[2]230
[2653]231    private void operatorGraph_InitialOperatorChanged(object sender, EventArgs e) {
[2790]232      Prepare();
[2653]233    }
234
[2796]235    /// <summary>
236    /// Occurs when the operator graph was changed.
237    /// </summary>
[2653]238    public event EventHandler OperatorGraphChanged;
[2796]239    /// <summary>
240    /// Fires a new <c>OperatorGraphChanged</c> event.
241    /// </summary>
[2653]242    protected virtual void OnOperatorGraphChanged() {
243      if (OperatorGraphChanged != null)
244        OperatorGraphChanged(this, EventArgs.Empty);
245    }
[776]246    /// <summary>
[2653]247    /// Occurs when the execution time changed.
[776]248    /// </summary>
[2653]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)
[2793]255        ExecutionTimeChanged(this, EventArgs.Empty);
[2653]256    }
257    /// <summary>
[2790]258    /// Occurs when the execution is prepared for a new run.
[2653]259    /// </summary>
[2790]260    public event EventHandler Prepared;
[776]261    /// <summary>
[2790]262    /// Fires a new <c>Prepared</c> event.
[776]263    /// </summary>
[2790]264    protected virtual void OnPrepared() {
265      if (Prepared != null)
[2793]266        Prepared(this, EventArgs.Empty);
[2]267    }
[776]268    /// <summary>
[2653]269    /// Occurs when the execution is executed.
[776]270    /// </summary>
[2653]271    public event EventHandler Started;
[776]272    /// <summary>
[2653]273    /// Fires a new <c>Started</c> event.
[776]274    /// </summary>
[2653]275    protected virtual void OnStarted() {
276      if (Started != null)
[2793]277        Started(this, EventArgs.Empty);
[2]278    }
[776]279    /// <summary>
[2653]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)
[2793]288        Stopped(this, EventArgs.Empty);
[2653]289    }
[2851]290    protected virtual void OnCanceledChanged() { }
[2653]291    /// <summary>
[776]292    /// Occurs when an exception occured during the execution.
293    /// </summary>
[2474]294    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
[776]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>
[2]299    protected virtual void OnExceptionOccurred(Exception exception) {
300      if (ExceptionOccurred != null)
[2474]301        ExceptionOccurred(this, new EventArgs<Exception>(exception));
[2]302    }
303  }
304}
Note: See TracBrowser for help on using the repository browser.