-#if NET_4_0
//
// TaskCompletionSource.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 2011 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
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#if NET_4_0 || MOBILE
using System;
+using System.Collections.Generic;
namespace System.Threading.Tasks
{
public class TaskCompletionSource<TResult>
{
- Task<TResult> source;
+ readonly Task<TResult> source;
public TaskCompletionSource ()
+ : this (null, TaskCreationOptions.None)
{
- source = new Task<TResult> (null);
}
public TaskCompletionSource (object state)
+ : this (state, TaskCreationOptions.None)
{
- source = new Task<TResult> (null, state);
}
- public TaskCompletionSource (TaskCreationOptions options)
+ public TaskCompletionSource (TaskCreationOptions creationOptions)
+ : this (null, creationOptions)
{
- source = new Task<TResult> (null, options);
}
- public TaskCompletionSource (object state, TaskCreationOptions options)
+ public TaskCompletionSource (object state, TaskCreationOptions creationOptions)
{
- source = new Task<TResult> (null, state, options);
+ if ((creationOptions & System.Threading.Tasks.Task.WorkerTaskNotSupportedOptions) != 0)
+ throw new ArgumentOutOfRangeException ("creationOptions");
+
+ source = new Task<TResult> (TaskActionInvoker.Empty, state, CancellationToken.None, creationOptions, null);
+ source.SetupScheduler (TaskScheduler.Current);
}
public void SetCanceled ()
{
- if (!ApplyOperation (TaskStatus.Canceled, () => { source.Cancel (); source.CancelReal (); }))
+ if (!TrySetCanceled ())
ThrowInvalidException ();
}
- public void SetException (Exception e)
+ public void SetException (Exception exception)
+ {
+ if (exception == null)
+ throw new ArgumentNullException ("exception");
+
+ SetException (new Exception[] { exception });
+ }
+
+ public void SetException (IEnumerable<Exception> exceptions)
{
- if (!ApplyOperation (TaskStatus.Faulted, () => source.Exception = e))
+ if (!TrySetException (exceptions))
ThrowInvalidException ();
}
public void SetResult (TResult result)
{
- if (!ApplyOperation (TaskStatus.RanToCompletion, () => source.Result = result))
+ if (!TrySetResult (result))
ThrowInvalidException ();
}
- void ThrowInvalidException ()
+ static void ThrowInvalidException ()
{
throw new InvalidOperationException ("The underlying Task is already in one of the three final states: RanToCompletion, Faulted, or Canceled.");
}
public bool TrySetCanceled ()
{
- return ApplyOperation (TaskStatus.Canceled, () => { source.Cancel (); source.CancelReal (); });
+ return source.TrySetCanceled ();
}
- public bool TrySetException (Exception e)
+ public bool TrySetException (Exception exception)
{
- return ApplyOperation (TaskStatus.Faulted, () => source.Exception = e);
+ if (exception == null)
+ throw new ArgumentNullException ("exception");
+
+ return TrySetException (new Exception[] { exception });
}
- public bool TrySetResult (TResult result)
+ public bool TrySetException (IEnumerable<Exception> exceptions)
{
- return ApplyOperation (TaskStatus.RanToCompletion, () => source.Result = result);
- }
-
- bool ApplyOperation (TaskStatus newStatus, Action action)
- {
- if (CheckInvalidState ())
- return false;
-
- if (action != null)
- action ();
- source.Status = newStatus;
-
- return true;
+ if (exceptions == null)
+ throw new ArgumentNullException ("exceptions");
+
+ var aggregate = new AggregateException (exceptions);
+ if (aggregate.InnerExceptions.Count == 0)
+ throw new ArgumentNullException ("exceptions");
+
+ return source.TrySetException (aggregate);
}
- bool CheckInvalidState ()
+ public bool TrySetResult (TResult result)
{
- return source.Status == TaskStatus.RanToCompletion ||
- source.Status == TaskStatus.Faulted ||
- source.Status == TaskStatus.Canceled;
-
+ return source.TrySetResult (result);
}
-
+
public Task<TResult> Task {
get {
return source;