* Makefile.am:
[monodevelop.git] / extras / MonoDevelop.Debugger.Mdb / Mono.Debugging.Server.Mdb / TimedEvaluator.cs
blob9e17d861ed533788276852f2137b26e805cafb18
1 // EvaluationContext.cs
2 //
3 // Author:
4 // Lluis Sanchez Gual <lluis@novell.com>
5 //
6 // Copyright (c) 2008 Novell, Inc (http://www.novell.com)
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 // THE SOFTWARE.
28 using System;
29 using System.Collections.Generic;
30 using System.Threading;
32 namespace DebuggerServer
34 public class TimedEvaluator
36 int runTimeout = DebuggerServer.DefaultAsyncSwitchTimeout;
37 int maxThreads = 1;
39 object runningLock = new object ();
40 Queue<Task> pendingTasks = new Queue<Task> ();
41 AutoResetEvent newTaskEvent = new AutoResetEvent (false);
42 Task currentTask;
43 int runningThreads;
44 bool mainThreadBusy;
45 bool useTimeout;
47 public TimedEvaluator (): this (true)
51 public TimedEvaluator (bool useTimeout)
53 this.useTimeout = useTimeout;
56 public bool Run (EvaluatorDelegate evaluator, EvaluatorDelegate delayedDoneCallback)
58 if (!useTimeout) {
59 SafeRun (evaluator);
60 return true;
63 Task task = new Task ();
64 task.Evaluator = evaluator;
65 task.FinishedCallback = delayedDoneCallback;
67 lock (runningLock) {
68 if (mainThreadBusy || runningThreads == 0) {
69 if (runningThreads < maxThreads) {
70 runningThreads++;
71 Thread tr = new Thread (Runner);
72 tr.IsBackground = true;
73 tr.Start ();
74 } else {
75 // The main thread is busy evaluating and we can't tell
76 // how much time it will take, so we can't wait for it.
77 task.TimedOut = true;
78 pendingTasks.Enqueue (task);
79 return false;
82 mainThreadBusy = true;
85 currentTask = task;
86 newTaskEvent.Set ();
87 task.RunningEvent.WaitOne ();
89 lock (task) {
90 if (!task.RunFinishedEvent.WaitOne (runTimeout, false)) {
91 task.TimedOut = true;
92 return false;
93 } else {
94 lock (runningLock) {
95 mainThreadBusy = false;
96 Monitor.PulseAll (runningLock);
100 return true;
103 void Runner ()
105 Task threadTask = null;
107 while (true) {
109 if (threadTask == null) {
110 newTaskEvent.WaitOne ();
111 threadTask = currentTask;
112 currentTask = null;
115 threadTask.RunningEvent.Set ();
116 DateTime t = DateTime.Now;
117 SafeRun (threadTask.Evaluator);
118 threadTask.RunFinishedEvent.Set ();
120 lock (threadTask) {
121 if (threadTask.TimedOut)
122 SafeRun (threadTask.FinishedCallback);
123 else {
124 threadTask = null;
125 continue; // Done. Keep waiting for more tasks.
129 threadTask = null;
131 // The task timed out, so more threads may already have
132 // been created while this one was busy.
134 lock (runningLock) {
135 Monitor.PulseAll (runningLock);
136 if (pendingTasks.Count > 0) {
137 // There is pending work to do.
138 threadTask = pendingTasks.Dequeue ();
140 else if (mainThreadBusy) {
141 // More threads have been created and all are busy.
142 // This will now be the main thread.
143 mainThreadBusy = false;
145 else {
146 // More threads have been created and one of them is waiting for tasks
147 // This thread is not needed anymore, die
148 runningThreads--;
149 break;
155 public void CancelAll ()
157 lock (runningLock) {
158 pendingTasks.Clear ();
162 public void WaitForStopped ()
164 lock (runningLock) {
165 while (mainThreadBusy)
166 Monitor.Wait (runningLock);
170 void SafeRun (EvaluatorDelegate del)
172 try {
173 del ();
174 } catch {
178 class Task
180 public AutoResetEvent RunningEvent = new AutoResetEvent (false);
181 public AutoResetEvent RunFinishedEvent = new AutoResetEvent (false);
182 public EvaluatorDelegate Evaluator;
183 public EvaluatorDelegate FinishedCallback;
184 public bool TimedOut;
188 public delegate void EvaluatorDelegate ();