Bug 15574. XML deserialization recursion: add array type to known_types?
[mono.git] / mcs / class / corlib / System.Threading.Tasks / Task.cs
index ef56d7a82e025289d0a81a458af81052119bd752..5eefcb7da5f87592bc67d2751e579f0b95ed1055 100644 (file)
@@ -1,6 +1,12 @@
+//
 // Task.cs
 //
+// Authors:
+//    Marek Safar  <marek.safar@gmail.com>
+//    Jérémie Laval <jeremie dot laval at xamarin dot com>
+//
 // Copyright (c) 2008 Jérémie "Garuma" Laval
+// Copyright 2011-2013 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
 //
 //
 
-#if NET_4_0 || MOBILE
+#if NET_4_0
 
 using System;
 using System.Threading;
 using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
 
 namespace System.Threading.Tasks
 {
-       [System.Diagnostics.DebuggerDisplay ("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")]
-       [System.Diagnostics.DebuggerTypeProxy ("System.Threading.Tasks.SystemThreadingTasks_TaskDebugView")]
+       [System.Diagnostics.DebuggerDisplay ("Id = {Id}, Status = {Status}")]
+       [System.Diagnostics.DebuggerTypeProxy (typeof (TaskDebuggerView))]
        public class Task : IDisposable, IAsyncResult
        {
                // With this attribute each thread has its own value so that it's correct for our Schedule code
                // and for Parent property.
                [System.ThreadStatic]
-               static Task         current;
-               [System.ThreadStatic]
-               static Action<Task> childWorkAdder;
+               static Task current;
                
-               Task parent;
+               // parent is the outer task in which this task is created
+               readonly Task parent;
+               // A reference to a Task on which this continuation is attached to
+               Task contAncestor;
                
                static int          id = -1;
-               static TaskFactory  defaultFactory = new TaskFactory ();
-               
-               CountdownEvent childTasks = new CountdownEvent (1);
+               static readonly TaskFactory defaultFactory = new TaskFactory ();
+
+               CountdownEvent childTasks;
                
                int                 taskId;
-               TaskCreationOptions taskCreationOptions;
+               TaskCreationOptions creationOptions;
                
-               IScheduler          scheduler;
-               TaskScheduler       taskScheduler;
+               internal TaskScheduler       scheduler;
 
-               ManualResetEventSlim schedWait = new ManualResetEventSlim (false);
-               
-               volatile AggregateException  exception;
-               volatile bool                exceptionObserved;
+               TaskExceptionSlot exSlot;
+               ManualResetEvent wait_handle;
 
                TaskStatus          status;
-               
-               Action<object> action;
+
+               TaskActionInvoker invoker;
                object         state;
-               AtomicBooleanValue executing;
+               internal AtomicBooleanValue executing;
 
-               ConcurrentQueue<EventHandler> completed;
+               TaskCompletionQueue<IContinuation> continuations;
 
                CancellationToken token;
+               CancellationTokenRegistration? cancellationRegistration;
 
-               public Task (Action action) : this (action, TaskCreationOptions.None)
+               internal const TaskCreationOptions WorkerTaskNotSupportedOptions = TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness;
+
+               const TaskCreationOptions MaxTaskCreationOptions =
+#if NET_4_5
+                       TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler |
+#endif
+                       TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent;
+
+               public Task (Action action)
+                       : this (action, TaskCreationOptions.None)
                {
                        
                }
                
-               public Task (Action action, TaskCreationOptions creationOptions) : this (action, CancellationToken.None, creationOptions)
+               public Task (Action action, TaskCreationOptions creationOptions)
+                       : this (action, CancellationToken.None, creationOptions)
                {
                        
                }
                
-               public Task (Action action, CancellationToken cancellationToken) : this (action, cancellationToken, TaskCreationOptions.None)
+               public Task (Action action, CancellationToken cancellationToken)
+                       : this (action, cancellationToken, TaskCreationOptions.None)
                {
                        
                }
                
                public Task (Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
-                       : this ((o) => { if (action != null) action (); }, null, cancellationToken, creationOptions)
+                       : this (TaskActionInvoker.Create (action), null, cancellationToken, creationOptions, current)
                {
+                       if (action == null)
+                               throw new ArgumentNullException ("action");
+                       if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
+                               throw new ArgumentOutOfRangeException ("creationOptions");
                }
                
-               public Task (Action<object> action, object state) : this (action, state, TaskCreationOptions.None)
+               public Task (Action<object> action, object state)
+                       : this (action, state, TaskCreationOptions.None)
                {       
                }
                
@@ -104,45 +127,44 @@ namespace System.Threading.Tasks
                }
 
                public Task (Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
-                       : this (action, state, cancellationToken, creationOptions, current)
+                       : this (TaskActionInvoker.Create (action), state, cancellationToken, creationOptions, current)
                {
-
+                       if (action == null)
+                               throw new ArgumentNullException ("action");
+                       if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
+                               throw new ArgumentOutOfRangeException ("creationOptions");
                }
 
-               internal Task (Action<object> action,
-                              object state,
-                              CancellationToken cancellationToken,
-                              TaskCreationOptions creationOptions,
-                              Task parent)
+               internal Task (TaskActionInvoker invoker, object state, CancellationToken cancellationToken,
+                              TaskCreationOptions creationOptions, Task parent = null, Task contAncestor = null, bool ignoreCancellation = false)
                {
-                       this.taskCreationOptions = creationOptions;
-                       this.action              = action == null ? EmptyFunc : action;
-                       this.state               = state;
-                       this.taskId              = Interlocked.Increment (ref id);
-                       this.status              = TaskStatus.Created;
-                       this.token               = cancellationToken;
-                       this.parent              = parent;
+                       this.invoker         = invoker;
+                       this.creationOptions = creationOptions;
+                       this.state           = state;
+                       this.taskId          = Interlocked.Increment (ref id);
+                       this.token           = cancellationToken;
+                       this.parent          = parent = parent == null ? current : parent;
+                       this.contAncestor    = contAncestor;
+                       this.status          = cancellationToken.IsCancellationRequested && !ignoreCancellation ? TaskStatus.Canceled : TaskStatus.Created;
 
-                       // Process taskCreationOptions
-                       if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null)
+                       // Process creationOptions
+#if NET_4_5
+                       if (parent != null && HasFlag (creationOptions, TaskCreationOptions.AttachedToParent)
+                           && !HasFlag (parent.CreationOptions, TaskCreationOptions.DenyChildAttach))
+#else
+                       if (parent != null && HasFlag (creationOptions, TaskCreationOptions.AttachedToParent))
+#endif
                                parent.AddChild ();
-               }
 
-               ~Task ()
-               {
-                       if (exception != null && !exceptionObserved)
-                               throw exception;
+                       if (token.CanBeCanceled && !ignoreCancellation)
+                               cancellationRegistration = token.Register (l => ((Task) l).CancelReal (), this);
                }
 
-               bool CheckTaskOptions (TaskCreationOptions opt, TaskCreationOptions member)
+               static bool HasFlag (TaskCreationOptions opt, TaskCreationOptions member)
                {
                        return (opt & member) == member;
                }
 
-               static void EmptyFunc (object o)
-               {
-               }
-
                #region Start
                public void Start ()
                {
@@ -151,31 +173,23 @@ namespace System.Threading.Tasks
                
                public void Start (TaskScheduler scheduler)
                {
-                       Start (ProxifyScheduler (scheduler));
-               }
-               
-               void Start (IScheduler scheduler)
-               {
+                       if (scheduler == null)
+                               throw new ArgumentNullException ("scheduler");
+
+                       if (status >= TaskStatus.WaitingToRun)
+                               throw new InvalidOperationException ("The Task is not in a valid state to be started.");
+
+                       if (IsContinuation)
+                               throw new InvalidOperationException ("Start may not be called on a continuation task");
+
                        SetupScheduler (scheduler);
                        Schedule ();
                }
 
-               internal void SetupScheduler (TaskScheduler tscheduler)
-               {
-                       SetupScheduler (ProxifyScheduler (tscheduler));
-               }
-
-               internal void SetupScheduler (IScheduler scheduler)
+               internal void SetupScheduler (TaskScheduler scheduler)
                {
                        this.scheduler = scheduler;
-                       status = TaskStatus.WaitingForActivation;
-                       schedWait.Set ();
-               }
-               
-               IScheduler ProxifyScheduler (TaskScheduler tscheduler)
-               {
-                       IScheduler sched = tscheduler as IScheduler;
-                       return sched != null ? sched : new SchedulerProxy (tscheduler);
+                       Status = TaskStatus.WaitingForActivation;
                }
                
                public void RunSynchronously ()
@@ -185,12 +199,31 @@ namespace System.Threading.Tasks
                
                public void RunSynchronously (TaskScheduler scheduler)
                {
-                       if (this.Status != TaskStatus.Created)
+                       if (scheduler == null)
+                               throw new ArgumentNullException ("scheduler");
+
+                       if (Status > TaskStatus.WaitingForActivation)
                                throw new InvalidOperationException ("The task is not in a valid state to be started");
-                       if (scheduler.TryExecuteTask (this))
-                               return;
 
-                       Start (scheduler);
+                       if (IsContinuation)
+                               throw new InvalidOperationException ("RunSynchronously may not be called on a continuation task");
+
+                       RunSynchronouslyCore (scheduler);
+               }
+
+               internal void RunSynchronouslyCore (TaskScheduler scheduler)
+               {
+                       SetupScheduler (scheduler);
+                       Status = TaskStatus.WaitingToRun;
+
+                       try {
+                               if (scheduler.RunInline (this, false))
+                                       return;
+                       } catch (Exception inner) {
+                               throw new TaskSchedulerException (inner);
+                       }
+
+                       Schedule ();
                        Wait ();
                }
                #endregion
@@ -218,11 +251,21 @@ namespace System.Threading.Tasks
                
                public Task ContinueWith (Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
                {
-                       Task continuation = new Task ((o) => continuationAction ((Task)o),
-                                                     this,
-                                                     cancellationToken,
-                                                     GetCreationOptions (continuationOptions),
-                                                     this);
+                       if (continuationAction == null)
+                               throw new ArgumentNullException ("continuationAction");
+                       if (scheduler == null)
+                               throw new ArgumentNullException ("scheduler");
+
+                       return ContinueWith (TaskActionInvoker.Create (continuationAction), cancellationToken, continuationOptions, scheduler);
+               }
+
+               internal Task ContinueWith (TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+               {
+                       var lazyCancellation = false;
+#if NET_4_5
+                       lazyCancellation = (continuationOptions & TaskContinuationOptions.LazyCancellation) > 0;
+#endif
+                       var continuation = new Task (invoker, null, cancellationToken, GetCreationOptions (continuationOptions), null, this, lazyCancellation);
                        ContinueWithCore (continuation, continuationOptions, scheduler);
 
                        return continuation;
@@ -256,107 +299,57 @@ namespace System.Threading.Tasks
                        if (scheduler == null)
                                throw new ArgumentNullException ("scheduler");
 
-                       Task<TResult> t = new Task<TResult> ((o) => continuationFunction ((Task)o),
-                                                            this,
-                                                            cancellationToken,
-                                                            GetCreationOptions (continuationOptions),
-                                                            this);
-                       
-                       ContinueWithCore (t, continuationOptions, scheduler);
-                       
-                       return t;
+                       return ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction), cancellationToken, continuationOptions, scheduler);
                }
-               
-               internal void ContinueWithCore (Task continuation, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+
+               internal Task<TResult> ContinueWith<TResult> (TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
                {
-                       ContinueWithCore (continuation, continuationOptions, scheduler, () => true);
+                       var lazyCancellation = false;
+#if NET_4_5
+                       lazyCancellation = (continuationOptions & TaskContinuationOptions.LazyCancellation) > 0;
+#endif
+                       var continuation = new Task<TResult> (invoker, null, cancellationToken, GetCreationOptions (continuationOptions), parent, this, lazyCancellation);
+                       ContinueWithCore (continuation, continuationOptions, scheduler);
+
+                       return continuation;
                }
-               
-               internal void ContinueWithCore (Task continuation, TaskContinuationOptions kind,
-                                               TaskScheduler scheduler, Func<bool> predicate)
+       
+               internal void ContinueWithCore (Task continuation, TaskContinuationOptions options, TaskScheduler scheduler)
                {
+                       const TaskContinuationOptions wrongRan = TaskContinuationOptions.NotOnRanToCompletion | TaskContinuationOptions.OnlyOnRanToCompletion;
+                       const TaskContinuationOptions wrongCanceled = TaskContinuationOptions.NotOnCanceled | TaskContinuationOptions.OnlyOnCanceled;
+                       const TaskContinuationOptions wrongFaulted = TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.OnlyOnFaulted;
+
+                       if (((options & wrongRan) == wrongRan) || ((options & wrongCanceled) == wrongCanceled) || ((options & wrongFaulted) == wrongFaulted))
+                               throw new ArgumentException ("continuationOptions", "Some options are mutually exclusive");
+
                        // Already set the scheduler so that user can call Wait and that sort of stuff
-                       continuation.taskScheduler = scheduler;
-                       continuation.scheduler = ProxifyScheduler (scheduler);
-                       continuation.schedWait.Set ();
-                       continuation.status = TaskStatus.WaitingForActivation;
-                       
-                       AtomicBoolean launched = new AtomicBoolean ();
-                       EventHandler action = delegate (object sender, EventArgs e) {
-                               if (launched.TryRelaxedSet ()) {
-                                       if (!predicate ())
-                                               return;
-
-                                       if (!ContinuationStatusCheck (kind)) {
-                                               continuation.CancelReal ();
-                                               continuation.Dispose ();
-                                               
-                                               return;
-                                       }
-                                       
-                                       CheckAndSchedule (continuation, kind, scheduler, sender == null);
-                               }
-                       };
-                       
+                       continuation.scheduler = scheduler;
+                       continuation.Status = TaskStatus.WaitingForActivation;
+
+                       ContinueWith (new TaskContinuation (continuation, options));
+               }
+               
+               internal void ContinueWith (IContinuation continuation)
+               {
                        if (IsCompleted) {
-                               action (null, EventArgs.Empty);
+                               continuation.Execute ();
                                return;
                        }
                        
-                       if (completed == null)
-                               Interlocked.CompareExchange (ref completed, new ConcurrentQueue<EventHandler> (), null);
-                       completed.Enqueue (action);
+                       continuations.Add (continuation);
                        
                        // Retry in case completion was achieved but event adding was too late
-                       if (IsCompleted)
-                               action (null, EventArgs.Empty);
+                       if (IsCompleted && continuations.Remove (continuation))
+                               continuation.Execute ();
                }
 
-               
-               bool ContinuationStatusCheck (TaskContinuationOptions kind)
+               internal void RemoveContinuation (IContinuation continuation)
                {
-                       if (kind == TaskContinuationOptions.None)
-                               return true;
-                       
-                       int kindCode = (int)kind;
-                       
-                       if (kindCode >= ((int)TaskContinuationOptions.NotOnRanToCompletion)) {
-                               if (status == TaskStatus.Canceled) {
-                                       if (kind == TaskContinuationOptions.NotOnCanceled)
-                                               return false;
-                                       if (kind == TaskContinuationOptions.OnlyOnFaulted)
-                                               return false;
-                                       if (kind == TaskContinuationOptions.OnlyOnRanToCompletion)
-                                               return false;
-                               } else if (status == TaskStatus.Faulted) {
-                                       if (kind == TaskContinuationOptions.NotOnFaulted)
-                                               return false;
-                                       if (kind == TaskContinuationOptions.OnlyOnCanceled)
-                                               return false;
-                                       if (kind == TaskContinuationOptions.OnlyOnRanToCompletion)
-                                               return false;
-                               } else if (status == TaskStatus.RanToCompletion) {
-                                       if (kind == TaskContinuationOptions.NotOnRanToCompletion)
-                                               return false;
-                                       if (kind == TaskContinuationOptions.OnlyOnFaulted)
-                                               return false;
-                                       if (kind == TaskContinuationOptions.OnlyOnCanceled)
-                                               return false;
-                               }
-                       }
-                       
-                       return true;
+                       continuations.Remove (continuation);
                }
-               
-               void CheckAndSchedule (Task continuation, TaskContinuationOptions options, TaskScheduler scheduler, bool fromCaller)
-               {
-                       if ((options & TaskContinuationOptions.ExecuteSynchronously) > 0)
-                               continuation.ThreadStart ();
-                       else
-                               continuation.Start (scheduler);
-               }
-               
-               internal TaskCreationOptions GetCreationOptions (TaskContinuationOptions kind)
+
+               static internal TaskCreationOptions GetCreationOptions (TaskContinuationOptions kind)
                {
                        TaskCreationOptions options = TaskCreationOptions.None;
                        if ((kind & TaskContinuationOptions.AttachedToParent) > 0)
@@ -372,19 +365,9 @@ namespace System.Threading.Tasks
                
                #region Internal and protected thingies
                internal void Schedule ()
-               {       
-                       status = TaskStatus.WaitingToRun;
-                       
-                       // If worker is null it means it is a local one, revert to the old behavior
-                       if (childWorkAdder == null || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) {
-                               scheduler.AddWork (this);
-                       } else {
-                               /* Like the semantic of the ABP paper describe it, we add ourselves to the bottom 
-                                * of our Parent Task's ThreadWorker deque. It's ok to do that since we are in
-                                * the correct Thread during the creation
-                                */
-                               childWorkAdder (this);
-                       }
+               {
+                       Status = TaskStatus.WaitingToRun;
+                       scheduler.QueueTask (this);
                }
                
                void ThreadStart ()
@@ -396,8 +379,22 @@ namespace System.Threading.Tasks
                        if (!executing.TryRelaxedSet ())
                                return;
 
+                       // Disable CancellationToken direct cancellation
+                       if (cancellationRegistration != null) {
+                               cancellationRegistration.Value.Dispose ();
+                               cancellationRegistration = null;
+                       }
+
+                       // If Task are ran inline on the same thread we might trash these values
+                       var saveCurrent = current;
+                       var saveScheduler = TaskScheduler.Current;
+
                        current = this;
-                       TaskScheduler.Current = taskScheduler;
+#if NET_4_5
+                       TaskScheduler.Current = HasFlag (creationOptions, TaskCreationOptions.HideScheduler) ? TaskScheduler.Default : scheduler;
+#else
+                       TaskScheduler.Current = scheduler;
+#endif
                        
                        if (!token.IsCancellationRequested) {
                                
@@ -406,7 +403,7 @@ namespace System.Threading.Tasks
                                try {
                                        InnerInvoke ();
                                } catch (OperationCanceledException oce) {
-                                       if (oce.CancellationToken == token)
+                                       if (token != CancellationToken.None && oce.CancellationToken == token)
                                                CancelReal ();
                                        else
                                                HandleGenericException (oce);
@@ -416,74 +413,168 @@ namespace System.Threading.Tasks
                        } else {
                                CancelReal ();
                        }
-                       
+
+                       if (saveCurrent != null)
+                               current = saveCurrent;
+                       if (saveScheduler != null)
+                               TaskScheduler.Current = saveScheduler;
                        Finish ();
                }
-               
-               internal void Execute (Action<Task> childAdder)
+
+               internal bool TrySetCanceled ()
+               {
+                       if (IsCompleted)
+                               return false;
+                       
+                       if (!executing.TryRelaxedSet ()) {
+                               var sw = new SpinWait ();
+                               while (!IsCompleted)
+                                       sw.SpinOnce ();
+
+                               return false;
+                       }
+                       
+                       CancelReal ();
+                       return true;
+               }
+
+               internal bool TrySetException (AggregateException aggregate)
+               {
+                       if (IsCompleted)
+                               return false;
+                       
+                       if (!executing.TryRelaxedSet ()) {
+                               var sw = new SpinWait ();
+                               while (!IsCompleted)
+                                       sw.SpinOnce ();
+
+                               return false;
+                       }
+                       
+                       HandleGenericException (aggregate);
+                       return true;
+               }
+
+               internal bool TrySetExceptionObserved ()
+               {
+                       if (exSlot != null) {
+                               exSlot.Observed = true;
+                               return true;
+                       }
+                       return false;
+               }
+
+               internal void Execute ()
                {
-                       childWorkAdder = childAdder;
                        ThreadStart ();
                }
                
                internal void AddChild ()
                {
+                       if (childTasks == null)
+                               Interlocked.CompareExchange (ref childTasks, new CountdownEvent (1), null);
                        childTasks.AddCount ();
                }
 
-               internal void ChildCompleted ()
+               internal void ChildCompleted (AggregateException childEx)
                {
+                       if (childEx != null) {
+                               if (ExceptionSlot.ChildExceptions == null)
+                                       Interlocked.CompareExchange (ref ExceptionSlot.ChildExceptions, new ConcurrentQueue<AggregateException> (), null);
+                               ExceptionSlot.ChildExceptions.Enqueue (childEx);
+                       }
+
                        if (childTasks.Signal () && status == TaskStatus.WaitingForChildrenToComplete) {
-                               status = TaskStatus.RanToCompletion;
-                               
+                               ProcessChildExceptions ();
+                               Status = exSlot == null ? TaskStatus.RanToCompletion : TaskStatus.Faulted;
                                ProcessCompleteDelegates ();
+                               if (parent != null &&
+#if NET_4_5
+                                   !HasFlag (parent.CreationOptions, TaskCreationOptions.DenyChildAttach) &&
+#endif
+                                       HasFlag (creationOptions, TaskCreationOptions.AttachedToParent))
+                                       parent.ChildCompleted (this.Exception);
                        }
                }
 
-               internal virtual void InnerInvoke ()
+               void InnerInvoke ()
                {
-                       if (action != null)
-                               action (state);
-                       // Set action to null so that the GC can collect the delegate and thus
-                       // any big object references that the user might have captured in an anonymous method
-                       action = null;
-                       state = null;
+                       if (IsContinuation) {
+                               var ancestor = contAncestor;
+                               contAncestor = null;
+                               invoker.Invoke (ancestor, state, this);
+                       } else {
+                               invoker.Invoke (this, state, this);
+                       }
                }
                
                internal void Finish ()
                {
-                       // If there wasn't any child created in the task we set the CountdownEvent
-                       childTasks.Signal ();
+                       // If there was children created and they all finished, we set the countdown
+                       if (childTasks != null) {
+                               if (childTasks.Signal ())
+                                       ProcessChildExceptions (true);
+                       }
                        
                        // Don't override Canceled or Faulted
                        if (status == TaskStatus.Running) {
-                               if (childTasks.IsSet)
-                                       status = TaskStatus.RanToCompletion;
+                               if (childTasks == null || childTasks.IsSet)
+                                       Status = TaskStatus.RanToCompletion;
                                else
-                                       status = TaskStatus.WaitingForChildrenToComplete;
+                                       Status = TaskStatus.WaitingForChildrenToComplete;
                        }
-               
-                       if (status != TaskStatus.WaitingForChildrenToComplete)
-                               ProcessCompleteDelegates ();
-                       
-                       // Reset the current thingies
-                       current = null;
-                       TaskScheduler.Current = null;
-                       
+
+                       if (wait_handle != null)
+                               wait_handle.Set ();
+
                        // Tell parent that we are finished
-                       if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null){
-                               parent.ChildCompleted ();
+                       if (parent != null && HasFlag (creationOptions, TaskCreationOptions.AttachedToParent) &&
+#if NET_4_5
+                           !HasFlag (parent.CreationOptions, TaskCreationOptions.DenyChildAttach) &&
+#endif
+                               status != TaskStatus.WaitingForChildrenToComplete) {
+                               parent.ChildCompleted (this.Exception);
                        }
+
+                       // Completions are already processed when task is canceled or faulted
+                       if (status == TaskStatus.RanToCompletion)
+                               ProcessCompleteDelegates ();
+
+                       // Reset the current thingies
+                       if (current == this)
+                               current = null;
+                       if (TaskScheduler.Current == scheduler)
+                               TaskScheduler.Current = null;
+
+                       if (cancellationRegistration.HasValue)
+                               cancellationRegistration.Value.Dispose ();
                }
 
                void ProcessCompleteDelegates ()
                {
-                       if (completed == null)
+                       if (continuations.HasElements) {
+                               IContinuation continuation;
+                               while (continuations.TryGetNextCompletion (out continuation))
+                                       continuation.Execute ();
+                       }
+               }
+
+               void ProcessChildExceptions (bool isParent = false)
+               {
+                       if (exSlot == null || exSlot.ChildExceptions == null)
                                return;
 
-                       EventHandler handler;
-                       while (completed.TryDequeue (out handler))
-                               handler (this, EventArgs.Empty);
+                       if (ExceptionSlot.Exception == null)
+                               exSlot.Exception = new AggregateException ();
+
+                       AggregateException childEx;
+                       while (exSlot.ChildExceptions.TryDequeue (out childEx))
+                               exSlot.Exception.AddChildException (childEx);
+
+                       if (isParent) {
+                               Status = TaskStatus.Faulted;
+                               ProcessCompleteDelegates ();                    
+                       }
                }
                #endregion
                
@@ -491,38 +582,48 @@ namespace System.Threading.Tasks
                
                internal void CancelReal ()
                {
-                       status = TaskStatus.Canceled;
+                       Status = TaskStatus.Canceled;
+
+                       if (wait_handle != null)
+                               wait_handle.Set ();
+
+                       ProcessCompleteDelegates ();
                }
 
-               internal void HandleGenericException (Exception e)
+               void HandleGenericException (Exception e)
                {
                        HandleGenericException (new AggregateException (e));
                }
 
-               internal void HandleGenericException (AggregateException e)
+               void HandleGenericException (AggregateException e)
                {
-                       exception = e;
-                       status = TaskStatus.Faulted;
-                       if (taskScheduler != null && taskScheduler.FireUnobservedEvent (exception).Observed)
-                               exceptionObserved = true;
+                       ExceptionSlot.Exception = e;
+                       Thread.MemoryBarrier ();
+                       Status = TaskStatus.Faulted;
+
+                       if (wait_handle != null)
+                               wait_handle.Set ();
+
+                       ProcessCompleteDelegates ();
+               }
+
+               internal bool WaitOnChildren ()
+               {
+                       if (Status == TaskStatus.WaitingForChildrenToComplete && childTasks != null) {
+                               childTasks.Wait ();
+                               return true;
+                       }
+                       return false;
                }
                
                public void Wait ()
                {
-                       if (scheduler == null)
-                               schedWait.Wait ();
-                       
-                       if (!IsCompleted)
-                               scheduler.ParticipateUntil (this);
-                       if (exception != null)
-                               throw exception;
-                       if (IsCanceled)
-                               throw new AggregateException (new TaskCanceledException (this));
+                       Wait (Timeout.Infinite, CancellationToken.None);
                }
 
                public void Wait (CancellationToken cancellationToken)
                {
-                       Wait (-1, cancellationToken);
+                       Wait (Timeout.Infinite, cancellationToken);
                }
                
                public bool Wait (TimeSpan timeout)
@@ -540,98 +641,115 @@ namespace System.Threading.Tasks
                        if (millisecondsTimeout < -1)
                                throw new ArgumentOutOfRangeException ("millisecondsTimeout");
 
-                       if (millisecondsTimeout == -1 && token == CancellationToken.None) {
-                               Wait ();
+                       bool result = WaitCore (millisecondsTimeout, cancellationToken);
+
+                       if (IsCanceled)
+                               throw new AggregateException (new TaskCanceledException (this));
+
+                       var exception = Exception;
+                       if (exception != null)
+                               throw exception;
+
+                       return result;
+               }
+
+               internal bool WaitCore (int millisecondsTimeout, CancellationToken cancellationToken)
+               {
+                       if (IsCompleted)
                                return true;
-                       }
 
-                       Watch watch = Watch.StartNew ();
+                       // If the task is ready to be run and we were supposed to wait on it indefinitely without cancellation, just run it
+                       if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == Timeout.Infinite && scheduler != null && !cancellationToken.CanBeCanceled)
+                               scheduler.RunInline (this, true);
 
-                       if (scheduler == null) {
-                               schedWait.Wait (millisecondsTimeout, cancellationToken);
-                               millisecondsTimeout = ComputeTimeout (millisecondsTimeout, watch);
-                       }
+                       bool result = true;
 
-                       ManualResetEventSlim predicateEvt = new ManualResetEventSlim (false);
-                       if (cancellationToken != CancellationToken.None) {
-                               cancellationToken.Register (predicateEvt.Set);
-                               cancellationToken.ThrowIfCancellationRequested ();
+                       if (!IsCompleted) {
+                               var continuation = new ManualResetContinuation ();
+                               try {
+                                       ContinueWith (continuation);
+                                       result = continuation.Event.Wait (millisecondsTimeout, cancellationToken);
+                               } finally {
+                                       if (!result)
+                                               RemoveContinuation (continuation);
+                                       continuation.Dispose ();
+                               }
                        }
 
-                       bool result = scheduler.ParticipateUntil (this, predicateEvt, millisecondsTimeout);
-
-                       if (exception != null)
-                               throw exception;
-                       if (IsCanceled)
-                               throw new AggregateException (new TaskCanceledException (this));
-                       
-                       return !result;
+                       return result;
                }
                
                public static void WaitAll (params Task[] tasks)
                {
-                       if (tasks == null)
-                               throw new ArgumentNullException ("tasks");
-                       if (tasks.Length == 0)
-                               throw new ArgumentException ("tasks is empty", "tasks");
-                       
-                       foreach (var t in tasks)
-                               t.Wait ();
+                       WaitAll (tasks, Timeout.Infinite, CancellationToken.None);
                }
 
                public static void WaitAll (Task[] tasks, CancellationToken cancellationToken)
                {
-                       if (tasks == null)
-                               throw new ArgumentNullException ("tasks");
-                       if (tasks.Length == 0)
-                               throw new ArgumentException ("tasks is empty", "tasks");
-                       
-                       foreach (var t in tasks)
-                               t.Wait (cancellationToken);
+                       WaitAll (tasks, Timeout.Infinite, cancellationToken);
                }
                
                public static bool WaitAll (Task[] tasks, TimeSpan timeout)
                {
-                       if (tasks == null)
-                               throw new ArgumentNullException ("tasks");
-                       if (tasks.Length == 0)
-                               throw new ArgumentException ("tasks is empty", "tasks");
-                       
-                       bool result = true;
-                       foreach (var t in tasks)
-                               result &= t.Wait (timeout);
-                       return result;
+                       return WaitAll (tasks, CheckTimeout (timeout), CancellationToken.None);
                }
                
                public static bool WaitAll (Task[] tasks, int millisecondsTimeout)
                {
-                       if (tasks == null)
-                               throw new ArgumentNullException ("tasks");
-                       if (tasks.Length == 0)
-                               throw new ArgumentException ("tasks is empty", "tasks");
-                       
-                       bool result = true;
-                       foreach (var t in tasks)
-                               result &= t.Wait (millisecondsTimeout);
-                       return result;
+                       return WaitAll (tasks, millisecondsTimeout, CancellationToken.None);
                }
                
                public static bool WaitAll (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
                {
                        if (tasks == null)
                                throw new ArgumentNullException ("tasks");
-                       if (tasks.Length == 0)
-                               throw new ArgumentException ("tasks is empty", "tasks");
-                       
+
                        bool result = true;
-                       foreach (var t in tasks)
-                               result &= t.Wait (millisecondsTimeout, cancellationToken);
+                       foreach (var t in tasks) {
+                               if (t == null)
+                                       throw new ArgumentException ("tasks", "the tasks argument contains a null element");
+
+                               result &= t.Status == TaskStatus.RanToCompletion;
+                       }
+
+                       if (!result) {
+                               var continuation = new CountdownContinuation (tasks.Length);
+                               try {
+                                       foreach (var t in tasks)
+                                               t.ContinueWith (continuation);
+
+                                       result = continuation.Event.Wait (millisecondsTimeout, cancellationToken);
+                               } finally {
+                                       List<Exception> exceptions = null;
+
+                                       foreach (var t in tasks) {
+                                               if (result) {
+                                                       if (t.Status == TaskStatus.RanToCompletion)
+                                                               continue;
+                                                       if (exceptions == null)
+                                                               exceptions = new List<Exception> ();
+                                                       if (t.Exception != null)
+                                                               exceptions.AddRange (t.Exception.InnerExceptions);
+                                                       else
+                                                               exceptions.Add (new TaskCanceledException (t));
+                                               } else {
+                                                       t.RemoveContinuation (continuation);
+                                               }
+                                       }
+
+                                       continuation.Dispose ();
+
+                                       if (exceptions != null)
+                                               throw new AggregateException (exceptions);
+                               }
+                       }
+
                        return result;
                }
                
                public static int WaitAny (params Task[] tasks)
                {
-                       return WaitAny (tasks, -1, CancellationToken.None);
+                       return WaitAny (tasks, Timeout.Infinite, CancellationToken.None);
                }
 
                public static int WaitAny (Task[] tasks, TimeSpan timeout)
@@ -641,90 +759,53 @@ namespace System.Threading.Tasks
                
                public static int WaitAny (Task[] tasks, int millisecondsTimeout)
                {
-                       if (millisecondsTimeout < -1)
-                               throw new ArgumentOutOfRangeException ("millisecondsTimeout");
-
-                       if (millisecondsTimeout == -1)
-                               return WaitAny (tasks);
-
                        return WaitAny (tasks, millisecondsTimeout, CancellationToken.None);
                }
 
                public static int WaitAny (Task[] tasks, CancellationToken cancellationToken)
                {
-                       return WaitAny (tasks, -1, cancellationToken);
+                       return WaitAny (tasks, Timeout.Infinite, cancellationToken);
                }
 
                public static int WaitAny (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
                {
                        if (tasks == null)
                                throw new ArgumentNullException ("tasks");
-                       if (tasks.Length == 0)
-                               throw new ArgumentException ("tasks is empty", "tasks");
-                       if (tasks.Length == 1) {
-                               tasks[0].Wait (millisecondsTimeout, cancellationToken);
-                               return 0;
-                       }
-                       
-                       int numFinished = 0;
-                       int indexFirstFinished = -1;
-                       int index = 0;
-                       IScheduler sched = null;
-                       Task task = null;
-                       Watch watch = Watch.StartNew ();
-                       ManualResetEventSlim predicateEvt = new ManualResetEventSlim (false);
-
-                       foreach (Task t in tasks) {
-                               int indexResult = index++;
-                               t.ContinueWith (delegate {
-                                       if (numFinished >= 1)
-                                               return;
-                                       int result = Interlocked.Increment (ref numFinished);
-
-                                       // Check if we are the first to have finished
-                                       if (result == 1)
-                                               indexFirstFinished = indexResult;
-
-                                       // Stop waiting
-                                       predicateEvt.Set ();
-                               }, TaskContinuationOptions.ExecuteSynchronously);
-
-                               if (sched == null && t.scheduler != null) {
-                                       task = t;
-                                       sched = t.scheduler;
-                               }
-                       }
-
-                       // If none of task have a scheduler we are forced to wait for at least one to start
-                       if (sched == null) {
-                               var handles = Array.ConvertAll (tasks, t => t.schedWait.WaitHandle);
-                               int shandle = -1;
-                               if ((shandle = WaitHandle.WaitAny (handles, millisecondsTimeout)) == WaitHandle.WaitTimeout)
-                                       return -1;
-                               sched = tasks[shandle].scheduler;
-                               task = tasks[shandle];
-                               millisecondsTimeout = ComputeTimeout (millisecondsTimeout, watch);
-                       }
+                       if (millisecondsTimeout < -1)
+                               throw new ArgumentOutOfRangeException ("millisecondsTimeout");
+                       CheckForNullTasks (tasks);
 
-                       // One task already finished
-                       if (indexFirstFinished != -1)
-                               return indexFirstFinished;
+                       if (tasks.Length > 0) {
+                               var continuation = new ManualResetContinuation ();
+                               bool result = false;
+                               try {
+                                       for (int i = 0; i < tasks.Length; i++) {
+                                               var t = tasks[i];
+                                               if (t.IsCompleted)
+                                                       return i;
+                                               t.ContinueWith (continuation);
+                                       }
 
-                       if (cancellationToken != CancellationToken.None) {
-                               cancellationToken.Register (predicateEvt.Set);
-                               cancellationToken.ThrowIfCancellationRequested ();
+                                       if (!(result = continuation.Event.Wait (millisecondsTimeout, cancellationToken)))
+                                               return -1;
+                               } finally {
+                                       if (!result)
+                                               foreach (var t in tasks)
+                                                       t.RemoveContinuation (continuation);
+                                       continuation.Dispose ();
+                               }
                        }
 
-                       sched.ParticipateUntil (task, predicateEvt, millisecondsTimeout);
-
-                       // Index update is still not done
-                       if (indexFirstFinished == -1) {
-                               SpinWait wait = new SpinWait ();
-                               while (indexFirstFinished == -1)
-                                       wait.SpinOnce ();
+                       int firstFinished = -1;
+                       for (int i = 0; i < tasks.Length; i++) {
+                               var t = tasks[i];
+                               if (t.IsCompleted) {
+                                       firstFinished = i;
+                                       break;
+                               }
                        }
 
-                       return indexFirstFinished;
+                       return firstFinished;
                }
 
                static int CheckTimeout (TimeSpan timeout)
@@ -736,31 +817,419 @@ namespace System.Threading.Tasks
                        }
                }
 
-               static int ComputeTimeout (int millisecondsTimeout, Watch watch)
+               static void CheckForNullTasks (Task[] tasks)
                {
-                       return millisecondsTimeout == -1 ? -1 : (int)Math.Max (watch.ElapsedMilliseconds - millisecondsTimeout, 1);
+                       foreach (var t in tasks)
+                               if (t == null)
+                                       throw new ArgumentException ("tasks", "the tasks argument contains a null element");
                }
-
                #endregion
                
                #region Dispose
                public void Dispose ()
                {
-                       Dispose (true);
+                       Dispose (true);                 
                }
                
                protected virtual void Dispose (bool disposing)
                {
+                       if (!IsCompleted)
+                               throw new InvalidOperationException ("A task may only be disposed if it is in a completion state");
+
                        // Set action to null so that the GC can collect the delegate and thus
                        // any big object references that the user might have captured in a anonymous method
                        if (disposing) {
-                               action = null;
+                               invoker = null;
                                state = null;
+                               if (cancellationRegistration != null)
+                                       cancellationRegistration.Value.Dispose ();
+                               if (wait_handle != null)
+                                       wait_handle.Dispose ();
                        }
                }
                #endregion
+
+#if NET_4_5
+               public
+#else
+               internal
+#endif
+               Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken,
+                                                                 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+               {
+                       if (continuationAction == null)
+                               throw new ArgumentNullException ("continuationAction");
+                       if (scheduler == null)
+                               throw new ArgumentNullException ("scheduler");
+
+                       Task continuation = new Task (TaskActionInvoker.Create (continuationAction),
+                                                                                 state, cancellationToken,
+                                                                                 GetCreationOptions (continuationOptions),
+                                                     parent,
+                                                     this);
+                       ContinueWithCore (continuation, continuationOptions, scheduler);
+
+                       return continuation;
+               }
                
+#if NET_4_5
+
+               public ConfiguredTaskAwaitable ConfigureAwait (bool continueOnCapturedContext)
+               {
+                       return new ConfiguredTaskAwaitable (this, continueOnCapturedContext);
+               }
+
+               public Task ContinueWith (Action<Task, object> continuationAction, object state)
+               {
+                       return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
+               }
+
+               public Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
+               {
+                       return ContinueWith (continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
+               }
+
+               public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
+               {
+                       return ContinueWith (continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
+               }
+
+               public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
+               {
+                       return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
+               }
+
+               public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state)
+               {
+                       return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
+               }
+
+               public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
+               {
+                       return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
+               }
+
+               public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
+               {
+                       return ContinueWith<TResult> (continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
+               }
+
+               public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
+               {
+                       return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
+               }
+
+               public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken,
+                                                                                                       TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+               {
+                       if (continuationFunction == null)
+                               throw new ArgumentNullException ("continuationFunction");
+                       if (scheduler == null)
+                               throw new ArgumentNullException ("scheduler");
+
+                       var t = new Task<TResult> (TaskActionInvoker.Create (continuationFunction),
+                                                  state,
+                                                  cancellationToken,
+                                                  GetCreationOptions (continuationOptions),
+                                                  parent,
+                                                  this);
+
+                       ContinueWithCore (t, continuationOptions, scheduler);
+
+                       return t;
+               }
+
+               public static Task Delay (int millisecondsDelay)
+               {
+                       return Delay (millisecondsDelay, CancellationToken.None);
+               }
+
+               public static Task Delay (TimeSpan delay)
+               {
+                       return Delay (CheckTimeout (delay), CancellationToken.None);
+               }
+
+               public static Task Delay (TimeSpan delay, CancellationToken cancellationToken)
+               {
+                       return Delay (CheckTimeout (delay), cancellationToken);
+               }
+
+               public static Task Delay (int millisecondsDelay, CancellationToken cancellationToken)
+               {
+                       if (millisecondsDelay < -1)
+                               throw new ArgumentOutOfRangeException ("millisecondsDelay");
+
+                       if (cancellationToken.IsCancellationRequested)
+                               return TaskConstants.Canceled;
+
+                       var task = new Task (TaskActionInvoker.Empty, null, cancellationToken, TaskCreationOptions.None, null, null);
+                       task.SetupScheduler (TaskScheduler.Default);
+
+                       if (millisecondsDelay != Timeout.Infinite) {
+                               var timer = new Timer (delegate (object state) {
+                                       var t = (Task) state;
+                                       if (t.Status == TaskStatus.WaitingForActivation) {
+                                               t.Status = TaskStatus.Running;
+                                               t.Finish ();
+                                       }
+                               }, task, millisecondsDelay, -1);
+
+                               task.ContinueWith (new DisposeContinuation (timer));
+                       }
+
+                       return task;
+               }
+
+               public static Task<TResult> FromResult<TResult> (TResult result)
+               {
+                       var tcs = new TaskCompletionSource<TResult> ();
+                       tcs.SetResult (result);
+                       return tcs.Task;
+               }
+
+               public TaskAwaiter GetAwaiter ()
+               {
+                       return new TaskAwaiter (this);
+               }
+
+               public static Task Run (Action action)
+               {
+                       return Run (action, CancellationToken.None);
+               }
+
+               public static Task Run (Action action, CancellationToken cancellationToken)
+               {
+                       if (cancellationToken.IsCancellationRequested)
+                               return TaskConstants.Canceled;
+
+                       return Task.Factory.StartNew (action, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+               }
+
+               public static Task Run (Func<Task> function)
+               {
+                       return Run (function, CancellationToken.None);
+               }
+
+               public static Task Run (Func<Task> function, CancellationToken cancellationToken)
+               {
+                       if (cancellationToken.IsCancellationRequested)
+                               return TaskConstants.Canceled;
+
+                       return TaskExtensionsImpl.Unwrap (Task.Factory.StartNew (function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
+               }
+
+               public static Task<TResult> Run<TResult> (Func<TResult> function)
+               {
+                       return Run (function, CancellationToken.None);
+               }
+
+               public static Task<TResult> Run<TResult> (Func<TResult> function, CancellationToken cancellationToken)
+               {
+                       if (cancellationToken.IsCancellationRequested)
+                               return TaskConstants<TResult>.Canceled;
+
+                       return Task.Factory.StartNew (function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+               }
+
+               public static Task<TResult> Run<TResult> (Func<Task<TResult>> function)
+               {
+                       return Run (function, CancellationToken.None);
+               }
+
+               public static Task<TResult> Run<TResult> (Func<Task<TResult>> function, CancellationToken cancellationToken)
+               {
+                       if (cancellationToken.IsCancellationRequested)
+                               return TaskConstants<TResult>.Canceled;
+
+                       return TaskExtensionsImpl.Unwrap (Task.Factory.StartNew (function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default));
+               }
+
+               public static Task WhenAll (params Task[] tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       return WhenAllCore (tasks);
+               }
+
+               public static Task WhenAll (IEnumerable<Task> tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       // Call ToList on input enumeration or we end up
+                       // enumerating it more than once
+                       return WhenAllCore (new List<Task> (tasks));
+               }
+
+               public static Task<TResult[]> WhenAll<TResult> (params Task<TResult>[] tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       return WhenAllCore<TResult> (tasks);
+               }
+
+               public static Task<TResult[]> WhenAll<TResult> (IEnumerable<Task<TResult>> tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       // Call ToList on input enumeration or we end up
+                       // enumerating it more than once
+                       return WhenAllCore<TResult> (new List<Task<TResult>> (tasks));
+               }
+
+               internal static Task<TResult[]> WhenAllCore<TResult> (IList<Task<TResult>> tasks)
+               {
+                       if (tasks.Count == 0)
+                               return FromResult(new TResult[0]);
+
+                       foreach (var t in tasks) {
+                               if (t == null)
+                                       throw new ArgumentException ("tasks", "the tasks argument contains a null element");
+                       }
+
+                       var task = new Task<TResult[]> (TaskActionInvoker.Empty, null, CancellationToken.None, TaskCreationOptions.None, null, TaskConstants.Finished);
+                       task.SetupScheduler (TaskScheduler.Current);
+
+                       var continuation = new WhenAllContinuation<TResult> (task, tasks);
+                       foreach (var t in tasks)
+                               t.ContinueWith (continuation);
+
+                       return task;
+               }
+
+               public static Task<Task> WhenAny (params Task[] tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       return WhenAnyCore (tasks);
+               }
+
+               public static Task<Task> WhenAny (IEnumerable<Task> tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       return WhenAnyCore (new List<Task> (tasks));
+               }
+
+               public static Task<Task<TResult>> WhenAny<TResult> (params Task<TResult>[] tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       return WhenAnyCore<TResult> (tasks);
+               }
+
+               public static Task<Task<TResult>> WhenAny<TResult> (IEnumerable<Task<TResult>> tasks)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       return WhenAnyCore<TResult> (new List<Task<TResult>> (tasks));
+               }
+
+               static Task<Task<TResult>> WhenAnyCore<TResult> (IList<Task<TResult>> tasks)
+               {
+                       if (tasks.Count == 0)
+                               throw new ArgumentException ("The tasks argument contains no tasks", "tasks");
+
+                       int completed_index = -1;
+                       for (int i = 0; i < tasks.Count; ++i) {
+                               var t = tasks[i];
+                               if (t == null)
+                                       throw new ArgumentException ("tasks", "the tasks argument contains a null element");
+
+                               if (t.IsCompleted && completed_index < 0)
+                                       completed_index = i;
+                       }
+
+                       var task = new Task<Task<TResult>> (TaskActionInvoker.Empty, null, CancellationToken.None, TaskCreationOptions.None, null, TaskConstants.Finished);
+
+                       if (completed_index > 0) {
+                               task.TrySetResult (tasks[completed_index]);
+                               return task;
+                       }
+
+                       task.SetupScheduler (TaskScheduler.Current);
+
+                       var continuation = new WhenAnyContinuation<Task<TResult>> (task, tasks);
+                       foreach (var t in tasks)
+                               t.ContinueWith (continuation);
+
+                       return task;
+               }
+
+               public static YieldAwaitable Yield ()
+               {
+                       return new YieldAwaitable ();
+               }
+#endif
+
+               internal static Task WhenAllCore (IList<Task> tasks)
+               {
+                       bool all_completed = true;
+                       foreach (var t in tasks) {
+                               if (t == null)
+                                       throw new ArgumentException ("tasks", "the tasks argument contains a null element");
+
+                               all_completed &= t.Status == TaskStatus.RanToCompletion;
+                       }
+
+                       if (all_completed)
+                               return TaskConstants.Finished;
+
+                       var task = new Task (TaskActionInvoker.Empty, null, CancellationToken.None, TaskCreationOptions.None, null, TaskConstants.Finished);
+                       task.SetupScheduler (TaskScheduler.Current);
+
+                       var continuation = new WhenAllContinuation (task, tasks);
+                       foreach (var t in tasks)
+                               t.ContinueWith (continuation);
+
+                       return task;
+               }
+
+               internal static Task<Task> WhenAnyCore (IList<Task> tasks)
+               {
+                       if (tasks.Count == 0)
+                               throw new ArgumentException ("The tasks argument contains no tasks", "tasks");
+
+                       int completed_index = -1;
+                       for (int i = 0; i < tasks.Count; ++i) {
+                               var t = tasks [i];
+                               if (t == null)
+                                       throw new ArgumentException ("tasks", "the tasks argument contains a null element");
+
+                               if (t.IsCompleted && completed_index < 0)
+                                       completed_index = i;
+                       }
+
+                       var task = new Task<Task> (TaskActionInvoker.Empty, null, CancellationToken.None, TaskCreationOptions.None, null, TaskConstants.Finished);
+
+                       if (completed_index > 0) {
+                               task.TrySetResult (tasks[completed_index]);
+                               return task;
+                       }
+
+                       task.SetupScheduler (TaskScheduler.Current);
+
+                       var continuation = new WhenAnyContinuation<Task> (task, tasks);
+                       foreach (var t in tasks)
+                               t.ContinueWith (continuation);
+
+                       return task;
+               }
                #region Properties
+
+               internal CancellationToken CancellationToken {
+                       get {
+                               return token;
+                       }
+               }
+
                public static TaskFactory Factory {
                        get {
                                return defaultFactory;
@@ -776,12 +1245,10 @@ namespace System.Threading.Tasks
                
                public AggregateException Exception {
                        get {
-                               exceptionObserved = true;
-                               
-                               return exception;       
-                       }
-                       internal set {
-                               exception = value;
+                               if (exSlot == null)
+                                       return null;
+                               exSlot.Observed = true;
+                               return exSlot.Exception;
                        }
                }
                
@@ -793,8 +1260,7 @@ namespace System.Threading.Tasks
 
                public bool IsCompleted {
                        get {
-                               return status == TaskStatus.RanToCompletion ||
-                                       status == TaskStatus.Canceled || status == TaskStatus.Faulted;
+                               return status >= TaskStatus.RanToCompletion;
                        }
                }
                
@@ -806,7 +1272,7 @@ namespace System.Threading.Tasks
 
                public TaskCreationOptions CreationOptions {
                        get {
-                               return taskCreationOptions;
+                               return creationOptions & MaxTaskCreationOptions;
                        }
                }
                
@@ -816,6 +1282,16 @@ namespace System.Threading.Tasks
                        }
                        internal set {
                                status = value;
+                               Thread.MemoryBarrier ();
+                       }
+               }
+
+               TaskExceptionSlot ExceptionSlot {
+                       get {
+                               if (exSlot != null)
+                                       return exSlot;
+                               Interlocked.CompareExchange (ref exSlot, new TaskExceptionSlot (this), null);
+                               return exSlot;
                        }
                }
 
@@ -833,7 +1309,13 @@ namespace System.Threading.Tasks
 
                WaitHandle IAsyncResult.AsyncWaitHandle {
                        get {
-                               return null;
+                               if (invoker == null)
+                                       throw new ObjectDisposedException (GetType ().ToString ());
+
+                               if (wait_handle == null)
+                                       Interlocked.CompareExchange (ref wait_handle, new ManualResetEvent (IsCompleted), null);
+
+                               return wait_handle;
                        }
                }
                
@@ -843,11 +1325,25 @@ namespace System.Threading.Tasks
                        }
                }
 
-               internal Task Parent {
+               bool IsContinuation {
+                       get {
+                               return contAncestor != null;
+                       }
+               }
+
+               internal Task ContinuationAncestor {
                        get {
-                               return parent;
+                               return contAncestor;
                        }
                }
+               
+               internal string DisplayActionMethod {
+                       get {
+                               Delegate d = invoker.Action;
+                               return d == null ? "<none>" : d.Method.ToString ();
+                       }
+               }
+               
                #endregion
        }
 }