#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Drawing; using System.Threading; using HeuristicLab.Common; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Core { /// /// Base class to represent an engine, which is an interpreter, holding the code, the data and /// the actual state, which is the runtime stack and a pointer onto the next operation. It represents /// one execution and can handle parallel executions. /// [Item("Engine", "A base class for engines.")] public abstract class Engine : Item, IEngine { public override Image ItemImage { get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Event; } } private OperatorGraph operatorGraph; /// /// Gets or sets the current operator graph. /// [Storable] public OperatorGraph OperatorGraph { get { return operatorGraph; } set { if (value == null) throw new ArgumentNullException(); if (value != operatorGraph) { if (operatorGraph != null) operatorGraph.InitialOperatorChanged -= new EventHandler(operatorGraph_InitialOperatorChanged); operatorGraph = value; if (operatorGraph != null) operatorGraph.InitialOperatorChanged += new EventHandler(operatorGraph_InitialOperatorChanged); OnOperatorGraphChanged(); Prepare(); } } } /// /// Field of the current instance that represent the global scope. /// [Storable] private IScope globalScope; /// /// Gets the current global scope. /// public IScope GlobalScope { get { return globalScope; } } [Storable] private TimeSpan executionTime; /// /// Gets or sets the execution time. /// /// Calls in the setter. public TimeSpan ExecutionTime { get { return executionTime; } protected set { executionTime = value; OnExecutionTimeChanged(); } } /// /// Field of the current instance that represent the execution stack. /// [Storable] private Stack executionStack; /// /// Gets the current execution stack. /// protected Stack ExecutionStack { get { return executionStack; } } /// /// Flag of the current instance whether it is currently running. /// private bool running; /// /// Gets information whether the instance is currently running. /// public bool Running { get { return running; } } /// /// Flag of the current instance whether it is canceled. /// private bool canceled; /// /// Gets information whether the instance is currently canceled. /// protected bool Canceled { get { return canceled; } private set { if (canceled != value) { canceled = value; OnCanceledChanged(); } } } /// /// Gets information whether the instance has already terminated. /// public bool Finished { get { return executionStack.Count == 0; } } /// /// Initializes a new instance of with a new global scope. /// protected Engine() { globalScope = new Scope("Global"); executionStack = new Stack(); OperatorGraph = new OperatorGraph(); } /// /// Clones the current instance (deep clone). /// /// Deep clone through method of helper class /// . /// Dictionary of all already clone objects. (Needed to avoid cycles.) /// The cloned object as . public override IDeepCloneable Clone(Cloner cloner) { Engine clone = (Engine)base.Clone(cloner); clone.OperatorGraph = (OperatorGraph)cloner.Clone(operatorGraph); clone.globalScope = (Scope)cloner.Clone(globalScope); clone.executionTime = executionTime; IOperation[] contexts = executionStack.ToArray(); for (int i = contexts.Length - 1; i >= 0; i--) clone.executionStack.Push((IOperation)cloner.Clone(contexts[i])); clone.running = running; clone.canceled = canceled; return clone; } public void Prepare(IOperation initialOperation) { Canceled = false; running = false; globalScope.Clear(); ExecutionTime = new TimeSpan(); executionStack.Clear(); if (initialOperation != null) executionStack.Push(initialOperation); OnPrepared(); } /// /// Sets myCanceled and myRunning to false. The global scope is cleared, /// the execution time is reset, the execution stack is cleared and a new /// with the initial operator is added.
/// Calls .
public void Prepare() { if (OperatorGraph.InitialOperator != null) Prepare(new ExecutionContext(null, OperatorGraph.InitialOperator, GlobalScope)); } /// /// Calls /// of class . public void Start() { running = true; Canceled = false; ThreadPool.QueueUserWorkItem(new WaitCallback(Run), null); } /// /// Calls /// of class . public void Step() { running = true; Canceled = false; ThreadPool.QueueUserWorkItem(new WaitCallback(RunStep), null); } /// /// Sets the protected flag myCanceled to true. public void Stop() { Canceled = true; } private void Run(object state) { OnStarted(); DateTime start = DateTime.Now; DateTime end; while ((!Canceled) && (!Finished)) { ProcessNextOperator(); end = DateTime.Now; ExecutionTime += end - start; start = end; } ExecutionTime += DateTime.Now - start; running = false; OnStopped(); } private void RunStep(object state) { OnStarted(); DateTime start = DateTime.Now; if ((!Canceled) && (!Finished)) ProcessNextOperator(); ExecutionTime += DateTime.Now - start; running = false; OnStopped(); } /// /// Performs the next operation. /// protected abstract void ProcessNextOperator(); private void operatorGraph_InitialOperatorChanged(object sender, EventArgs e) { Prepare(); } /// /// Occurs when the operator graph was changed. /// public event EventHandler OperatorGraphChanged; /// /// Fires a new OperatorGraphChanged event. /// protected virtual void OnOperatorGraphChanged() { if (OperatorGraphChanged != null) OperatorGraphChanged(this, EventArgs.Empty); } /// /// Occurs when the execution time changed. /// public event EventHandler ExecutionTimeChanged; /// /// Fires a new ExecutionTimeChanged event. /// protected virtual void OnExecutionTimeChanged() { if (ExecutionTimeChanged != null) ExecutionTimeChanged(this, EventArgs.Empty); } /// /// Occurs when the execution is prepared for a new run. /// public event EventHandler Prepared; /// /// Fires a new Prepared event. /// protected virtual void OnPrepared() { if (Prepared != null) Prepared(this, EventArgs.Empty); } /// /// Occurs when the execution is executed. /// public event EventHandler Started; /// /// Fires a new Started event. /// protected virtual void OnStarted() { if (Started != null) Started(this, EventArgs.Empty); } /// /// Occurs when the execution is finished. /// public event EventHandler Stopped; /// /// Fires a new Stopped event. /// protected virtual void OnStopped() { if (Stopped != null) Stopped(this, EventArgs.Empty); } protected virtual void OnCanceledChanged() { } /// /// Occurs when an exception occured during the execution. /// public event EventHandler> ExceptionOccurred; /// /// Aborts the execution and fires a new ExceptionOccurred event. /// /// The exception that was thrown. protected virtual void OnExceptionOccurred(Exception exception) { if (ExceptionOccurred != null) ExceptionOccurred(this, new EventArgs(exception)); } } }