1 // EvaluationContext.cs
4 // Lluis Sanchez Gual <lluis@novell.com>
6 // Copyright (c) 2008 Novell, Inc (http://www.novell.com)
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
29 using System
.Collections
.Generic
;
30 using System
.Threading
;
32 namespace DebuggerServer
34 public class TimedEvaluator
36 int runTimeout
= DebuggerServer
.DefaultAsyncSwitchTimeout
;
39 object runningLock
= new object ();
40 Queue
<Task
> pendingTasks
= new Queue
<Task
> ();
41 AutoResetEvent newTaskEvent
= new AutoResetEvent (false);
47 public TimedEvaluator (): this (true)
51 public TimedEvaluator (bool useTimeout
)
53 this.useTimeout
= useTimeout
;
56 public bool Run (EvaluatorDelegate evaluator
, EvaluatorDelegate delayedDoneCallback
)
63 Task task
= new Task ();
64 task
.Evaluator
= evaluator
;
65 task
.FinishedCallback
= delayedDoneCallback
;
68 if (mainThreadBusy
|| runningThreads
== 0) {
69 if (runningThreads
< maxThreads
) {
71 Thread tr
= new Thread (Runner
);
72 tr
.IsBackground
= true;
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.
78 pendingTasks
.Enqueue (task
);
82 mainThreadBusy
= true;
87 task
.RunningEvent
.WaitOne ();
90 if (!task
.RunFinishedEvent
.WaitOne (runTimeout
, false)) {
95 mainThreadBusy
= false;
96 Monitor
.PulseAll (runningLock
);
105 Task threadTask
= null;
109 if (threadTask
== null) {
110 newTaskEvent
.WaitOne ();
111 threadTask
= currentTask
;
115 threadTask
.RunningEvent
.Set ();
116 DateTime t
= DateTime
.Now
;
117 SafeRun (threadTask
.Evaluator
);
118 threadTask
.RunFinishedEvent
.Set ();
121 if (threadTask
.TimedOut
)
122 SafeRun (threadTask
.FinishedCallback
);
125 continue; // Done. Keep waiting for more tasks.
131 // The task timed out, so more threads may already have
132 // been created while this one was busy.
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;
146 // More threads have been created and one of them is waiting for tasks
147 // This thread is not needed anymore, die
155 public void CancelAll ()
158 pendingTasks
.Clear ();
162 public void WaitForStopped ()
165 while (mainThreadBusy
)
166 Monitor
.Wait (runningLock
);
170 void SafeRun (EvaluatorDelegate del
)
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 ();