/// <summary> /// Calculates the product of two mutlisets asynchronously with a timeout to restrict long running computations /// </summary> /// <param name="multiset">Multiset</param> /// <param name="other">Other Multiset</param> /// <param name="timeout">Timeout, if <=0 no timeout is used and product will be computed sychronously</param> /// <returns></returns> public static BaseMultiset ProductWithTimeout(this BaseMultiset multiset, BaseMultiset other, long timeout) { if (other is IdentityMultiset) return multiset; if (other is NullMultiset) return other; if (other.IsEmpty) return new NullMultiset(); if (timeout <= 0) { return multiset.Product(other); } //Invoke using an Async call Multiset productSet = new Multiset(); StopToken stop = new StopToken(); GenerateProductDelegate d = new GenerateProductDelegate(GenerateProduct); IAsyncResult r = d.BeginInvoke(multiset, other, productSet, stop, null, null); //Wait int t = (int)Math.Min(timeout, Int32.MaxValue); r.AsyncWaitHandle.WaitOne(t); if (!r.IsCompleted) { stop.ShouldStop = true; r.AsyncWaitHandle.WaitOne(); } return productSet; }
/// <summary> /// Method for generating product of two multisets asynchronously /// </summary> /// <param name="multiset">Multiset</param> /// <param name="other">Other Multiset</param> /// <param name="target">Mutliset to generate the product in</param> /// <param name="stop">Stop Token</param> private static void GenerateProduct(BaseMultiset multiset, BaseMultiset other, BaseMultiset target, StopToken stop) { foreach (ISet x in multiset.Sets) { foreach (ISet y in other.Sets) { target.Add(x.Join(y)); //if (stop.ShouldStop) break; } if (stop.ShouldStop) break; } }
private static void EvalProduct(ISet x, BaseMultiset other, PartitionedMultiset productSet, StopToken stop) { if (stop.ShouldStop) { return; } int id = productSet.GetNextBaseID(); foreach (ISet y in other.Sets) { id++; ISet z = x.Join(y); z.ID = id; productSet.Add(z); } if (stop.ShouldStop) { return; } }
/// <summary> /// Calculates the product of two mutlisets asynchronously with a timeout to restrict long running computations /// </summary> /// <param name="multiset">Multiset</param> /// <param name="other">Other Multiset</param> /// <param name="timeout">Timeout, if <=0 no timeout is used and product will be computed sychronously</param> /// <returns></returns> public static BaseMultiset ProductWithTimeout(this BaseMultiset multiset, BaseMultiset other, long timeout) { if (other is IdentityMultiset) { return(multiset); } if (other is NullMultiset) { return(other); } if (other.IsEmpty) { return(new NullMultiset()); } // If no timeout use default implementation if (timeout <= 0) { return(multiset.Product(other)); } // Otherwise Invoke using an Async call BaseMultiset productSet; #if NET40 if (Options.UsePLinqEvaluation) { if (multiset.Count >= other.Count) { productSet = new PartitionedMultiset(multiset.Count, other.Count); } else { productSet = new PartitionedMultiset(other.Count, multiset.Count); } } else { #endif productSet = new Multiset(); #if NET40 } #endif var stop = new StopToken(); var t = (int)Math.Min(timeout, int.MaxValue); #if NET40 || NETCORE var productTask = Task.Factory.StartNew(() => GenerateProduct(multiset, other, productSet, stop)); if (!productTask.Wait(t)) { stop.ShouldStop = true; productTask.Wait(); } return(productSet); #else GenerateProductDelegate d = new GenerateProductDelegate(GenerateProduct); IAsyncResult r = d.BeginInvoke(multiset, other, productSet, stop, null, null); // Wait r.AsyncWaitHandle.WaitOne(t); if (!r.IsCompleted) { stop.ShouldStop = true; r.AsyncWaitHandle.WaitOne(); } return(productSet); #endif }
/// <summary> /// Method for generating product of two multisets asynchronously /// </summary> /// <param name="multiset">Multiset</param> /// <param name="other">Other Multiset</param> /// <param name="target">Mutliset to generate the product in</param> /// <param name="stop">Stop Token</param> private static void GenerateProduct(BaseMultiset multiset, BaseMultiset other, BaseMultiset target, StopToken stop) { #if NET40 if (Options.UsePLinqEvaluation) { // Determine partition sizes so we can do a parallel product // Want to parallelize over whichever side is larger if (multiset.Count >= other.Count) { multiset.Sets.AsParallel().ForAll(x => EvalProduct(x, other, target as PartitionedMultiset, stop)); } else { other.Sets.AsParallel().ForAll(y => EvalProduct(y, multiset, target as PartitionedMultiset, stop)); } } else { #endif foreach (ISet x in multiset.Sets) { foreach (ISet y in other.Sets) { target.Add(x.Join(y)); // if (stop.ShouldStop) break; } if (stop.ShouldStop) { break; } } #if NET40 } #endif }