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

Last change on this file since 1608 was 1608, checked in by kopal, 11 years ago

some improvements in executionEngine

  • now plugins can be executed more than one time (check routine checks every 10ms if one of the plugins may execute)
  • commented out slowing debug logging of execution engine
File size: 13.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                CheckExecutableProtocol checkExecutableProtocol = new CheckExecutableProtocol(schedulers[0], workspaceModel, this);
82                schedulers[0].AddProtocol(checkExecutableProtocol);
83                checkExecutableProtocol.Start();
84
85                int counter=0;
86                foreach (PluginModel pluginModel in workspaceModel.AllPluginModels)
87                {
88                    PluginProtocol pluginProtocol = new PluginProtocol(schedulers[counter], pluginModel,this);
89                    pluginModel.PluginProtocol = pluginProtocol;
90                    schedulers[counter].AddProtocol(pluginProtocol);
91                    pluginModel.checkExecutable(pluginProtocol);
92                    pluginProtocol.Start();
93                    counter = (counter + 1) % (System.Environment.ProcessorCount*2);
94                }
95            }
96        }     
97     
98        /// <summary>
99        /// Stop the execution
100        /// </summary>
101        public void Stop()
102        {
103            //First stop all Gears4Net Schedulers
104            foreach (Scheduler scheduler in schedulers)
105            {
106                scheduler.Shutdown();
107            }
108            //Secondly stop alle plugins
109            foreach(PluginModel pluginModel in workspaceModel.AllPluginModels)
110            {
111                pluginModel.Plugin.Stop();
112            }
113            IsRunning = false;
114        }
115
116        /// <summary>
117        /// Pause the execution
118        /// </summary>
119        public void Pause()
120        {
121            //not implemented yet
122        }
123
124        /// <summary>
125        /// Use the logger of the WorkspaceManagerEditor
126        /// </summary>
127        /// <param name="message"></param>
128        /// <param name="level"></param>
129        public void GuiLogMessage(string message, NotificationLevel level)
130        {           
131            WorkspaceManagerEditor.GuiLogMessage(message, level);
132        }           
133    }
134
135    /// <summary>
136    /// Message send to scheduler for a Plugin to trigger the PreExecution
137    /// </summary>
138    public class MessagePreExecution : MessageBase
139    {
140        public PluginModel PluginModel;
141    }
142
143    /// <summary>
144    /// Message send to scheduler for a Plugin to trigger the Execution
145    /// </summary>
146    public class MessageExecution : MessageBase
147    {
148        public PluginModel PluginModel;
149    }
150
151    /// <summary>
152    /// Message send to scheduler for a Plugin to trigger the PostExecution
153    /// </summary>
154    public class MessagePostExecution : MessageBase
155    {
156        public PluginModel PluginModel;
157    }
158
159    /// <summary>
160    /// A Protocol for updating the GUI in time intervals
161    /// </summary>
162    public class UpdateGuiProtocol : ProtocolBase
163    {
164        private WorkspaceModel workspaceModel;
165        private ExecutionEngine executionEngine;
166
167        /// <summary>
168        /// Create a new protocol. Each protocol requires a scheduler which provides
169        /// a thread for execution.
170        /// </summary>
171        /// <param name="scheduler"></param>
172        public UpdateGuiProtocol(Scheduler scheduler, WorkspaceModel workspaceModel, ExecutionEngine executionEngine)
173            : base(scheduler)
174        {
175            this.workspaceModel = workspaceModel;
176            this.executionEngine = executionEngine;
177        }
178
179        /// <summary>
180        /// The main function of the protocol
181        /// </summary>
182        /// <param name="stateMachine"></param>
183        /// <returns></returns>
184        public override System.Collections.Generic.IEnumerator<ReceiverBase> Execute(AbstractStateMachine stateMachine)
185        {
186            while (this.executionEngine.IsRunning)
187            {
188                yield return Timeout(1000, HandleUpdateGui);
189            }
190        }
191
192        /// <summary>
193        /// Handler function for a message.
194        /// This handler must not block, because it executes inside the thread of the scheduler.
195        /// </summary>
196        /// <param name="msg"></param>
197        private void HandleUpdateGui()
198        {
199            //Get the gui Thread
200            this.workspaceModel.WorkspaceManagerEditor.Presentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
201            {
202                foreach (PluginModel pluginModel in workspaceModel.AllPluginModels)
203                {
204                    if (pluginModel.GuiNeedsUpdate)
205                    {
206                        //executionEngine.GuiLogMessage("UpdateGui for \"" + pluginModel.Name + "\"", NotificationLevel.Debug);
207                        pluginModel.GuiNeedsUpdate = false;
208                        pluginModel.paint();
209                        if (pluginModel.UpdateableView != null)
210                        {
211                            pluginModel.UpdateableView.update();
212                        }
213                    }
214                }
215            }
216            , null);
217        }
218    }
219
220    /// <summary>
221    /// A Protocol for updating the GUI in time intervals
222    /// </summary>
223    public class CheckExecutableProtocol : ProtocolBase
224    {
225        private WorkspaceModel workspaceModel;
226        private ExecutionEngine executionEngine;
227
228        /// <summary>
229        /// Create a new protocol. Each protocol requires a scheduler which provides
230        /// a thread for execution.
231        /// </summary>
232        /// <param name="scheduler"></param>
233        public CheckExecutableProtocol(Scheduler scheduler, WorkspaceModel workspaceModel, ExecutionEngine executionEngine)
234            : base(scheduler)
235        {
236            this.workspaceModel = workspaceModel;
237            this.executionEngine = executionEngine;
238        }
239
240        /// <summary>
241        /// The main function of the protocol
242        /// </summary>
243        /// <param name="stateMachine"></param>
244        /// <returns></returns>
245        public override System.Collections.Generic.IEnumerator<ReceiverBase> Execute(AbstractStateMachine stateMachine)
246        {
247            while (this.executionEngine.IsRunning)
248            {
249                yield return Timeout(10, HandleCheckExecutable);
250            }
251        }
252
253        /// <summary>
254        /// Handler function for a message.
255        /// This handler must not block, because it executes inside the thread of the scheduler.
256        /// </summary>
257        /// <param name="msg"></param>
258        private void HandleCheckExecutable()
259        {
260            foreach (PluginModel pluginModel in workspaceModel.AllPluginModels)
261            {
262                pluginModel.checkExecutable(pluginModel.PluginProtocol);
263            }
264        }
265    }
266
267    /// <summary>
268    /// A Protocol for a PluginModel
269    /// </summary>
270    public class PluginProtocol : ProtocolBase
271    {
272        private PluginModel pluginModel;
273        private ExecutionEngine executionEngine;
274
275        /// <summary>
276        /// Create a new protocol. Each protocol requires a scheduler which provides
277        /// a thread for execution.
278        /// </summary>
279        /// <param name="scheduler"></param>
280        public PluginProtocol(Scheduler scheduler, PluginModel pluginModel,ExecutionEngine executionEngine)
281            : base(scheduler)
282        {
283            this.pluginModel = pluginModel;
284            this.executionEngine = executionEngine;
285        }
286
287        /// <summary>
288        /// The main function of the protocol
289        /// </summary>
290        /// <param name="stateMachine"></param>
291        /// <returns></returns>
292        public override System.Collections.Generic.IEnumerator<ReceiverBase> Execute(AbstractStateMachine stateMachine)
293        {
294            while (this.executionEngine.IsRunning)
295            {
296                yield return Receive<MessagePreExecution>(null, this.HandlePreExecute);
297                MessageExecution msg_exec = new MessageExecution();
298                msg_exec.PluginModel = this.pluginModel;
299                this.BroadcastMessageReliably(msg_exec);
300                yield return Receive<MessageExecution>(null, this.HandleExecute);
301                MessagePostExecution msg_post = new MessagePostExecution();
302                msg_post.PluginModel = this.pluginModel;
303                this.BroadcastMessageReliably(msg_post);
304                yield return Receive<MessagePostExecution>(null, this.HandlePostExecute);
305            }
306        }
307
308        /// <summary>
309        /// Handler function for a message.
310        /// This handler must not block, because it executes inside the thread of the scheduler.
311        /// </summary>
312        /// <param name="msg"></param>
313        private void HandlePreExecute(MessagePreExecution msg)
314        {
315            //executionEngine.GuiLogMessage("HandlePreExecute for \"" + msg.PluginModel.Name + "\"", NotificationLevel.Debug);
316            msg.PluginModel.Plugin.PreExecution();
317        }
318
319        /// <summary>
320        /// Handler function for a message.
321        /// This handler must not block, because it executes inside the thread of the scheduler.
322        /// </summary>
323        /// <param name="msg"></param>
324        private void HandleExecute(MessageExecution msg)
325        {
326            //executionEngine.GuiLogMessage("HandleExecute for \"" + msg.PluginModel.Name + "\"", NotificationLevel.Debug);
327            //Fill the plugins Inputs with data
328            foreach (ConnectorModel connectorModel in pluginModel.InputConnectors)
329            {
330                if (connectorModel.HasData)
331                {
332                    PropertyInfo propertyInfo = pluginModel.Plugin.GetType().GetProperty(connectorModel.PropertyName);
333                    propertyInfo.SetValue(pluginModel.Plugin, connectorModel.Data, null);
334                    connectorModel.Data = null;
335                    connectorModel.HasData = false;
336                    connectorModel.InputConnection.Active = false;                   
337                }
338            }
339           
340            msg.PluginModel.Plugin.Execute();
341                       
342        }
343
344        /// <summary>
345        /// Handler function for a message.
346        /// This handler must not block, because it executes inside the thread of the scheduler.
347        /// </summary>
348        /// <param name="msg"></param>
349        private void HandlePostExecute(MessagePostExecution msg)
350        {
351            //executionEngine.GuiLogMessage("HandlePostExecute for \"" + msg.PluginModel.Name + "\"", NotificationLevel.Debug);
352            msg.PluginModel.Plugin.PostExecution();
353                     
354        }
355    }
356}
Note: See TracBrowser for help on using the repository browser.