source: trunk/CrypPlugins/WorkspaceManager/Execution/ExecutionEngine.cs @ 1607

Last change on this file since 1607 was 1607, checked in by kopal, 11 years ago
  • added multiple schedulers to have multi core support in executionEngine
  • added gears4net protocol to update gui changes in time intervals
    • added needed interface IUpdateableView for updateable view elements
File size: 11.0 KB
Line 
1/*                             
2   Copyright 2010 Nils Kopal, Viktor M.
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16
17using System;
18using System.Collections.Generic;
19using System.Linq;
20using System.Text;
21
22using WorkspaceManager.Model;
23using System.Threading;
24using System.Collections;
25using Cryptool.PluginBase;
26using System.Reflection;
27using Gears4Net;
28using System.Windows.Threading;
29
30namespace WorkspaceManager.Execution
31{
32    /// <summary>
33    /// Engine to execute a model of the WorkspaceManager
34    /// </summary>
35    public class ExecutionEngine
36    {
37        private WorkspaceManager WorkspaceManagerEditor;
38        private Scheduler[] schedulers;
39        private WorkspaceModel workspaceModel;
40     
41        /// <summary>
42        /// Creates a new ExecutionEngine
43        /// </summary>
44        /// <param name="workspaceManagerEditor"></param>
45        public ExecutionEngine(WorkspaceManager workspaceManagerEditor)
46        {
47            WorkspaceManagerEditor = workspaceManagerEditor;
48        }
49
50        /// <summary>
51        /// Is this ExecutionEngine running?
52        /// </summary>
53        public bool IsRunning
54        {
55            get;
56            private set;
57        }
58
59        /// <summary>
60        /// Execute the current Model
61        /// </summary>
62        /// <param name="workspaceModel"></param>
63        public void Execute(WorkspaceModel workspaceModel)
64        {
65            this.workspaceModel = workspaceModel;
66
67            if (!IsRunning)
68            {
69                IsRunning = true;
70
71                schedulers = new Scheduler[System.Environment.ProcessorCount*2];
72                for(int i=0;i<System.Environment.ProcessorCount*2;i++){
73                    schedulers[i] = new WinFormsScheduler("Scheduler" + i);
74                }
75
76                workspaceModel.resetStates();
77                UpdateGuiProtocol updateGuiProtocol = new UpdateGuiProtocol(schedulers[0], workspaceModel, this);
78                schedulers[0].AddProtocol(updateGuiProtocol);
79                updateGuiProtocol.Start();
80
81                int counter=0;
82                foreach (PluginModel pluginModel in workspaceModel.AllPluginModels)
83                {
84                    PluginProtocol pluginProtocol = new PluginProtocol(schedulers[counter], pluginModel,this);
85                    pluginModel.PluginProtocol = pluginProtocol;
86                    schedulers[counter].AddProtocol(pluginProtocol);
87                    pluginModel.checkExecutable(pluginProtocol);
88                    pluginProtocol.Start();
89                    counter = (counter + 1) % (System.Environment.ProcessorCount*2);
90                }
91            }
92        }     
93     
94        /// <summary>
95        /// Stop the execution
96        /// </summary>
97        public void Stop()
98        {
99            //First stop all Gears4Net Schedulers
100            foreach (Scheduler scheduler in schedulers)
101            {
102                scheduler.Shutdown();
103            }
104            //Secondly stop alle plugins
105            foreach(PluginModel pluginModel in workspaceModel.AllPluginModels)
106            {
107                pluginModel.Plugin.Stop();
108            }
109            IsRunning = false;
110        }
111
112        /// <summary>
113        /// Pause the execution
114        /// </summary>
115        public void Pause()
116        {
117            //not implemented yet
118        }
119
120        /// <summary>
121        /// Use the logger of the WorkspaceManagerEditor
122        /// </summary>
123        /// <param name="message"></param>
124        /// <param name="level"></param>
125        public void GuiLogMessage(string message, NotificationLevel level)
126        {           
127            WorkspaceManagerEditor.GuiLogMessage(message, level);
128        }           
129    }
130
131    /// <summary>
132    /// Message send to scheduler for a Plugin to trigger the PreExecution
133    /// </summary>
134    public class MessagePreExecution : MessageBase
135    {
136        public PluginModel PluginModel;
137    }
138
139    /// <summary>
140    /// Message send to scheduler for a Plugin to trigger the Execution
141    /// </summary>
142    public class MessageExecution : MessageBase
143    {
144        public PluginModel PluginModel;
145    }
146
147    /// <summary>
148    /// Message send to scheduler for a Plugin to trigger the PostExecution
149    /// </summary>
150    public class MessagePostExecution : MessageBase
151    {
152        public PluginModel PluginModel;
153    }
154
155    /// <summary>
156    /// A Protocol for updating the GUI in time intervals
157    /// </summary>
158    public class UpdateGuiProtocol : ProtocolBase
159    {
160        private WorkspaceModel workspaceModel;
161        private ExecutionEngine executionEngine;
162
163        /// <summary>
164        /// Create a new protocol. Each protocol requires a scheduler which provides
165        /// a thread for execution.
166        /// </summary>
167        /// <param name="scheduler"></param>
168        public UpdateGuiProtocol(Scheduler scheduler, WorkspaceModel workspaceModel, ExecutionEngine executionEngine)
169            : base(scheduler)
170        {
171            this.workspaceModel = workspaceModel;
172            this.executionEngine = executionEngine;
173        }
174
175        /// <summary>
176        /// The main function of the protocol
177        /// </summary>
178        /// <param name="stateMachine"></param>
179        /// <returns></returns>
180        public override System.Collections.Generic.IEnumerator<ReceiverBase> Execute(AbstractStateMachine stateMachine)
181        {
182            while (true)
183            {
184                yield return Timeout(1000, HandleUpdateGui);
185            }
186        }
187
188        /// <summary>
189        /// Handler function for a message.
190        /// This handler must not block, because it executes inside the thread of the scheduler.
191        /// </summary>
192        /// <param name="msg"></param>
193        private void HandleUpdateGui()
194        {
195            //Get the gui Thread
196            this.workspaceModel.WorkspaceManagerEditor.Presentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
197            {
198                foreach (PluginModel pluginModel in workspaceModel.AllPluginModels)
199                {
200                    if (pluginModel.GuiNeedsUpdate)
201                    {
202                        executionEngine.GuiLogMessage("UpdateGui for \"" + pluginModel.Name + "\"", NotificationLevel.Debug);
203                        pluginModel.GuiNeedsUpdate = false;
204                        pluginModel.paint();
205                        if (pluginModel.UpdateableView != null)
206                        {
207                            pluginModel.UpdateableView.update();
208                        }
209                    }
210                }
211            }
212            , null);
213        }
214    }
215   
216    /// <summary>
217    /// A Protocol for a PluginModel
218    /// </summary>
219    public class PluginProtocol : ProtocolBase
220    {
221        private PluginModel pluginModel;
222        private ExecutionEngine executionEngine;
223
224        /// <summary>
225        /// Create a new protocol. Each protocol requires a scheduler which provides
226        /// a thread for execution.
227        /// </summary>
228        /// <param name="scheduler"></param>
229        public PluginProtocol(Scheduler scheduler, PluginModel pluginModel,ExecutionEngine executionEngine)
230            : base(scheduler)
231        {
232            this.pluginModel = pluginModel;
233            this.executionEngine = executionEngine;
234        }
235
236        /// <summary>
237        /// The main function of the protocol
238        /// </summary>
239        /// <param name="stateMachine"></param>
240        /// <returns></returns>
241        public override System.Collections.Generic.IEnumerator<ReceiverBase> Execute(AbstractStateMachine stateMachine)
242        {
243            while (true)
244            {
245                yield return Receive<MessagePreExecution>(null, this.HandlePreExecute);
246                MessageExecution msg_exec = new MessageExecution();
247                msg_exec.PluginModel = this.pluginModel;
248                this.BroadcastMessageReliably(msg_exec);
249                yield return Receive<MessageExecution>(null, this.HandleExecute);
250                MessagePostExecution msg_post = new MessagePostExecution();
251                msg_post.PluginModel = this.pluginModel;
252                this.BroadcastMessageReliably(msg_post);
253                yield return Receive<MessagePostExecution>(null, this.HandlePostExecute);
254            }
255        }
256
257        /// <summary>
258        /// Handler function for a message.
259        /// This handler must not block, because it executes inside the thread of the scheduler.
260        /// </summary>
261        /// <param name="msg"></param>
262        private void HandlePreExecute(MessagePreExecution msg)
263        {
264            executionEngine.GuiLogMessage("HandlePreExecute for \"" + msg.PluginModel.Name + "\"", NotificationLevel.Debug);
265            msg.PluginModel.Plugin.PreExecution();
266        }
267
268        /// <summary>
269        /// Handler function for a message.
270        /// This handler must not block, because it executes inside the thread of the scheduler.
271        /// </summary>
272        /// <param name="msg"></param>
273        private void HandleExecute(MessageExecution msg)
274        {
275            executionEngine.GuiLogMessage("HandleExecute for \"" + msg.PluginModel.Name + "\"", NotificationLevel.Debug);
276            //Fill the plugins Inputs with data
277            foreach (ConnectorModel connectorModel in pluginModel.InputConnectors)
278            {
279                if (connectorModel.HasData)
280                {
281                    PropertyInfo propertyInfo = pluginModel.Plugin.GetType().GetProperty(connectorModel.PropertyName);
282                    propertyInfo.SetValue(pluginModel.Plugin, connectorModel.Data, null);
283                    connectorModel.Data = null;
284                    connectorModel.HasData = false;
285                    connectorModel.InputConnection.Active = false;
286                }
287            }
288            msg.PluginModel.Plugin.Execute();
289        }
290
291        /// <summary>
292        /// Handler function for a message.
293        /// This handler must not block, because it executes inside the thread of the scheduler.
294        /// </summary>
295        /// <param name="msg"></param>
296        private void HandlePostExecute(MessagePostExecution msg)
297        {
298            executionEngine.GuiLogMessage("HandlePostExecute for \"" + msg.PluginModel.Name + "\"", NotificationLevel.Debug);
299            msg.PluginModel.Plugin.PostExecution();
300        }
301    }
302}
Note: See TracBrowser for help on using the repository browser.