[Task Scheduler] Track re-entrant call to WorkerMethod from normal ThreadWorker and...
authorJérémie Laval <jeremie.laval@gmail.com>
Thu, 2 Dec 2010 18:12:51 +0000 (18:12 +0000)
committerJérémie Laval <jeremie.laval@gmail.com>
Fri, 3 Dec 2010 16:59:42 +0000 (16:59 +0000)
mcs/class/corlib/System.Threading.Tasks/ThreadWorker.cs

index 6397e0dbba42b2f4e75b4ee8916fead117b4bc39..88703678efb198d68e1f370cfc4e1acd780a456c 100644 (file)
@@ -32,6 +32,13 @@ namespace System.Threading.Tasks
        internal class ThreadWorker : IDisposable
        {
                Thread workerThread;
+
+               /* This field is used when a TheadWorker have to call Task.Wait
+                * which bring him back here with the static WorkerMethod although
+                * it's more optimized for him to continue calling its own WorkerMethod
+                */
+               [ThreadStatic]
+               static ThreadWorker autoReference;
                
                readonly IDequeOperations<Task> dDeque;
                readonly ThreadWorker[]         others;
@@ -114,6 +121,7 @@ namespace System.Threading.Tasks
                {
                        int sleepTime = 0;
                        SpinWait wait = new SpinWait ();
+                       autoReference = this;
                        
                        // Main loop
                        while (started == 1) {
@@ -202,13 +210,16 @@ namespace System.Threading.Tasks
                        while (!predicate ()) {
                                Task value;
                                
-                               // Dequeue only one item as we have restriction
-                               if (sharedWorkQueue.TryTake (out value)) {
-                                       if (value != null) {
+                               // If we are in fact a normal ThreadWorker, use our own deque
+                               if (autoReference != null) {
+                                       while (autoReference.dDeque.PopBottom (out value) == PopResult.Succeed && value != null) {
                                                if (CheckTaskFitness (value))
-                                                       value.Execute (null);
+                                                       value.Execute (autoReference.ChildWorkAdder);
                                                else
-                                                       sharedWorkQueue.TryAdd (value);
+                                                       autoReference.dDeque.PushBottom (value);
+
+                                               if (predicate ())
+                                                       return;
                                        }
                                }