#region /* ----------------------------------------------------------------------- * * * Copyright 2011-2012 GRNET S.A. All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and * documentation are those of the authors and should not be * interpreted as representing official policies, either expressed * or implied, of GRNET S.A. * * ----------------------------------------------------------------------- */ #endregion using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Pithos.Core { public static class TaskExtensions { public static Task Then(this Task first, Func> next) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); Contract.EndContractBlock(); return Then(first, next, CancellationToken.None); } public static Task Then(this Task first, Func next) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); Contract.EndContractBlock(); return Then(first, next, CancellationToken.None); } public static Task Then(this Task first, Func> next, CancellationToken cancellationToken) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); Contract.EndContractBlock(); Contract.Assume(TaskScheduler.Current!=null); var tcs = new TaskCompletionSource(); first.ContinueWith(delegate { if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions); else if (first.IsCanceled) tcs.TrySetCanceled(); else { try { var t = next(first.Result); if (t == null) tcs.TrySetCanceled(); else t.ContinueWith(delegate { if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions); else if (t.IsCanceled) tcs.TrySetCanceled(); else tcs.TrySetResult(t.Result); }, TaskContinuationOptions.ExecuteSynchronously); } catch (Exception exc) { tcs.TrySetException(exc); } } }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current); return tcs.Task; } public static Task Then(this Task first, Func next, CancellationToken cancellationToken) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); Contract.EndContractBlock(); Contract.Assume(TaskScheduler.Current != null); var tcs = new TaskCompletionSource(); first.ContinueWith(delegate { if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions); else if (first.IsCanceled) tcs.TrySetCanceled(); else { try { var t = next(first.Result); if (t == null) tcs.TrySetCanceled(); else t.ContinueWith(delegate { if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions); else if (t.IsCanceled) tcs.TrySetCanceled(); else tcs.TrySetResult(null); }, TaskContinuationOptions.ExecuteSynchronously); } catch (Exception exc) { tcs.TrySetException(exc); } } }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current); return tcs.Task; } public static void ReportExceptions(this Task task,Action OnError,Action OnSuccess ) { if (!task.IsCompleted) throw new InvalidOperationException("The task has not completed."); if (task.IsFaulted) task.Exception.Handle(exc=> { OnError(task.Exception); return true; }); else { OnSuccess(); } } public static bool TryRemove(this ObservableConcurrentCollection collection,T item) where T:class { var found = false; IProducerConsumerCollection items= collection; //Store the initial count var count = items.Count; for (var i = 0; i < count; i++) { T tempItem; //Take an item if (!items.TryTake(out tempItem)) return false; //If it isn't the one we are looking for if (tempItem != item) //put it back items.TryAdd(tempItem); else //otherwise skip it and flag succcess found = true; } return found; } public static bool TryAdd(this ObservableConcurrentCollection collection,T item) where T:class { if (collection==null) throw new ArgumentNullException("collection"); Contract.EndContractBlock(); if (item == null) return false; IProducerConsumerCollection items= collection; return items.TryAdd(item); } } }