Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / corlib / System.Threading.Tasks / TaskScheduler.cs
index fc43fbf0436c1b016a516505d49c5c223f663b85..ad3ce1f4ec86a6e18c124537cf32f1582d283583 100644 (file)
@@ -1,10 +1,12 @@
 // 
 // TaskScheduler.cs
 //  
-// Author:
+// Authors:
 //       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//       Marek Safar <marek.safar@gmail.com>
 // 
 // Copyright (c) 2009 Jérémie "Garuma" Laval
+// Copyright 2012 Xamarin, Inc (http://www.xamarin.com)
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // THE SOFTWARE.
 
 #if NET_4_0 || MOBILE
-using System;
-using System.Threading;
+
 using System.Collections.Generic;
+using System.Diagnostics;
 
 namespace System.Threading.Tasks
 {
-       [System.Diagnostics.DebuggerDisplay ("Id={Id}")]
-       [System.Diagnostics.DebuggerTypeProxy ("System.Threading.Tasks.TaskScheduler+SystemThreadingTasks_TaskSchedulerDebugView")]
+       [DebuggerDisplay ("Id={Id}")]
+       [DebuggerTypeProxy (typeof (TaskSchedulerDebuggerView))]
        public abstract class TaskScheduler
        {
-               static TaskScheduler defaultScheduler = new TpScheduler ();
-               SchedulerProxy proxy;
+               sealed class TaskSchedulerDebuggerView
+               {
+                       readonly TaskScheduler scheduler;
+
+                       public TaskSchedulerDebuggerView (TaskScheduler scheduler)
+                       {
+                               this.scheduler = scheduler;
+                       }
+
+                       public IEnumerable<Task> ScheduledTasks {
+                               get {
+                                       return scheduler.GetScheduledTasks ();
+                               }
+                       }
+               }
+
+               static readonly TaskScheduler defaultScheduler = new TpScheduler ();
                
                [ThreadStatic]
                static TaskScheduler currentScheduler;
@@ -49,16 +66,14 @@ namespace System.Threading.Tasks
                protected TaskScheduler ()
                {
                        this.id = Interlocked.Increment (ref lastId);
-                       this.proxy = new SchedulerProxy (this);
-               }
-
-               ~TaskScheduler ()
-               {
                }
                
                public static TaskScheduler FromCurrentSynchronizationContext ()
                {
                        var syncCtx = SynchronizationContext.Current;
+                       if (syncCtx == null)
+                               throw new InvalidOperationException ("The current SynchronizationContext is null and cannot be used as a TaskScheduler");
+
                        return new SynchronizationContextScheduler (syncCtx);
                }
                
@@ -88,30 +103,16 @@ namespace System.Threading.Tasks
                
                public virtual int MaximumConcurrencyLevel {
                        get {
-                               return Environment.ProcessorCount;
+                               return int.MaxValue;
                        }
                }
 
-               internal virtual void ParticipateUntil (Task task)
-               {
-                       proxy.ParticipateUntil (task);
-               }
-
-               internal virtual bool ParticipateUntil (Task task, ManualResetEventSlim predicateEvt, int millisecondsTimeout)
-               {
-                       return proxy.ParticipateUntil (task, predicateEvt, millisecondsTimeout);
-               }
-
-               internal virtual void PulseAll ()
-               {
-                       proxy.PulseAll ();
-               }
-
                protected abstract IEnumerable<Task> GetScheduledTasks ();
                protected internal abstract void QueueTask (Task task);
+
                protected internal virtual bool TryDequeue (Task task)
                {
-                       throw new NotSupportedException ();
+                       return false;
                }
 
                internal protected bool TryExecuteTask (Task task)
@@ -120,7 +121,10 @@ namespace System.Threading.Tasks
                                return false;
 
                        if (task.Status == TaskStatus.WaitingToRun) {
-                               task.Execute (null);
+                               task.Execute ();
+                               if (task.WaitOnChildren ())
+                                       task.Wait ();
+
                                return true;
                        }
 
@@ -129,17 +133,18 @@ namespace System.Threading.Tasks
 
                protected abstract bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued);
 
-               internal bool RunInline (Task task)
+               internal bool RunInline (Task task, bool taskWasPreviouslyQueued)
                {
-                       if (!TryExecuteTaskInline (task, false))
+                       if (!TryExecuteTaskInline (task, taskWasPreviouslyQueued))
                                return false;
 
                        if (!task.IsCompleted)
                                throw new InvalidOperationException ("The TryExecuteTaskInline call to the underlying scheduler succeeded, but the task body was not invoked");
+
                        return true;
                }
 
-               internal UnobservedTaskExceptionEventArgs FireUnobservedEvent (AggregateException e)
+               internal static UnobservedTaskExceptionEventArgs FireUnobservedEvent (Task task, AggregateException e)
                {
                        UnobservedTaskExceptionEventArgs args = new UnobservedTaskExceptionEventArgs (e);
                        
@@ -147,7 +152,7 @@ namespace System.Threading.Tasks
                        if (temp == null)
                                return args;
                        
-                       temp (this, args);
+                       temp (task, args);
                        
                        return args;
                }