forked from tsai/mathnet-numerics
Browse Source
Instead of a specific Silverlight version, we now provide a separate Portable Library assebly that supports .Net 4.0.1 and higher, Silverlight 5 ad well as .Net for Metro style apps (WinRT). New NuGet Package MathNet.Numerics.Portable with the portable library. Since MathNet.Numerics.Portable now supports silverlight, the normal package MathNet.Numerics no longer supports it (.Net 4 only). Reworked the common parallel execution infrastructure for more reasonable abstractions and better compatibility with portable libraries. Portable libraries do support parts of the TPL, but neither the Parallel class nor straight threading.la-knuth
106 changed files with 3430 additions and 1675 deletions
@ -0,0 +1,17 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
||||
|
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> |
||||
|
<id>MathNet.Numerics.Portable</id> |
||||
|
<version>1.0.0</version> |
||||
|
<title>Math.NET Numerics Portable Edition</title> |
||||
|
<summary>Math.NET Numerics, providing methods and algorithms for numerical computations in science, engineering and every day use. Supports .Net 4.0.3, SL5, WinRT.</summary> |
||||
|
<description>Math.NET Numerics is the numerical foundation of the Math.NET project, aiming to provide methods and algorithms for numerical computations in science, engineering and every day use. Numerics is the result of merging dnAnalytics with Math.NET Iridium and is intended to replace both. Portable edition, supports .Net 4.0.3, SL5, WinRT.</description> |
||||
|
<authors>Marcus Cuda, Christoph Ruegg, Jurgen Van Gael</authors> |
||||
|
<owners>Christoph Ruegg</owners> |
||||
|
<projectUrl>http://numerics.mathdotnet.com/</projectUrl> |
||||
|
<iconUrl>http://www.mathdotnet.com/images/MathNet128.png</iconUrl> |
||||
|
<licenseUrl>http://mathnetnumerics.codeplex.com/license</licenseUrl> |
||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance> |
||||
|
<tags>math numeric portable SL WinRT statistics probability integration interpolation linear algebra matrix fft</tags> |
||||
|
</metadata> |
||||
|
</package> |
||||
File diff suppressed because it is too large
@ -0,0 +1,11 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace MathNet.Numerics |
||||
|
{ |
||||
|
#if PORTABLE
|
||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] |
||||
|
public class SerializableAttribute : Attribute |
||||
|
{ |
||||
|
} |
||||
|
#endif
|
||||
|
} |
||||
File diff suppressed because it is too large
@ -1,9 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace MathNet.Numerics |
|
||||
{ |
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] |
|
||||
public class SerializableAttribute : Attribute |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
@ -1,65 +0,0 @@ |
|||||
// <copyright file="AggregateException.cs" company="Math.NET">
|
|
||||
// Math.NET Numerics, part of the Math.NET Project
|
|
||||
// http://mathnet.opensourcedotnet.info
|
|
||||
// Copyright (c) 2009 Math.NET
|
|
||||
// Permission is hereby granted, free of charge, to any person
|
|
||||
// obtaining a copy of this software and associated documentation
|
|
||||
// files (the "Software"), to deal in the Software without
|
|
||||
// restriction, including without limitation the rights to use,
|
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||
// copies of the Software, and to permit persons to whom the
|
|
||||
// Software is furnished to do so, subject to the following
|
|
||||
// conditions:
|
|
||||
// The above copyright notice and this permission notice shall be
|
|
||||
// included in all copies or substantial portions of the Software.
|
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace MathNet.Numerics.Threading |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Collections.ObjectModel; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents multiple errors that occur during application execution.
|
|
||||
/// </summary>
|
|
||||
public class AggregateException : Exception |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// List of the aggregated exceptions.
|
|
||||
/// </summary>
|
|
||||
private readonly IList<Exception> _exceptions = new List<Exception>(); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the AggregateException class with a specified error message and references to the inner exceptions that are the cause of this exception.
|
|
||||
/// </summary>
|
|
||||
/// <param name="exceptions">The exceptions that are the cause of the current exception.</param>
|
|
||||
public AggregateException(IEnumerable<Exception> exceptions) |
|
||||
{ |
|
||||
foreach (var exception in exceptions) |
|
||||
{ |
|
||||
this._exceptions.Add(exception); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a read-only collection of the Exception instances that caused the current exception.
|
|
||||
/// </summary>
|
|
||||
/// <value>A read-only collection of the Exception instances that caused the current exception</value>
|
|
||||
public ReadOnlyCollection<Exception> InnerExceptions |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
return new ReadOnlyCollection<Exception>(this._exceptions); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,485 +0,0 @@ |
|||||
// <copyright file="Parallel.cs" company="Math.NET">
|
|
||||
// Math.NET Numerics, part of the Math.NET Project
|
|
||||
// http://mathnet.opensourcedotnet.info
|
|
||||
//
|
|
||||
// Copyright (c) 2009 Math.NET
|
|
||||
//
|
|
||||
// Permission is hereby granted, free of charge, to any person
|
|
||||
// obtaining a copy of this software and associated documentation
|
|
||||
// files (the "Software"), to deal in the Software without
|
|
||||
// restriction, including without limitation the rights to use,
|
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||
// copies of the Software, and to permit persons to whom the
|
|
||||
// Software is furnished to do so, subject to the following
|
|
||||
// conditions:
|
|
||||
//
|
|
||||
// The above copyright notice and this permission notice shall be
|
|
||||
// included in all copies or substantial portions of the Software.
|
|
||||
//
|
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace MathNet.Numerics.Threading |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using Properties; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Provides support for parallel loops.
|
|
||||
/// </summary>
|
|
||||
internal static class Parallel |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The amount to scale the foreach buffer after each iteration.
|
|
||||
/// </summary>
|
|
||||
private const int ScalingFactor = 2; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// The maximum size of the foreach buffer.
|
|
||||
/// </summary>
|
|
||||
private const int MaxBlockSize = 65536; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// The initial size of the for each buffer.
|
|
||||
/// </summary>
|
|
||||
private const int IntialBlockSize = 1024; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Executes a for loop in which iterations may run in parallel.
|
|
||||
/// </summary>
|
|
||||
/// <param name="fromInclusive">The start index, inclusive.</param>
|
|
||||
/// <param name="toExclusive">The end index, exclusive.</param>
|
|
||||
/// <param name="body">The body to be invoked for each iteration.</param>
|
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="body"/> argument is null.</exception>
|
|
||||
/// <exception cref="AggregateException">At least one invocation of the body threw an exception.</exception>
|
|
||||
public static void For(int fromInclusive, int toExclusive, Action<int> body) |
|
||||
{ |
|
||||
if (body == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("body"); |
|
||||
} |
|
||||
|
|
||||
// fast forward execution if it's only one or none items
|
|
||||
var count = toExclusive - fromInclusive; |
|
||||
if (count <= 1) |
|
||||
{ |
|
||||
if (count == 1) |
|
||||
{ |
|
||||
body(fromInclusive); |
|
||||
} |
|
||||
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// fast forward execution in case parallelization is disabled
|
|
||||
if (Control.DisableParallelization |
|
||||
|| ThreadQueue.ThreadCount <= 1 |
|
||||
|| ThreadQueue.IsInWorkerThread) |
|
||||
{ |
|
||||
for (int i = fromInclusive; i < toExclusive; i++) |
|
||||
{ |
|
||||
body(i); |
|
||||
} |
|
||||
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var actions = new Action[ThreadQueue.ThreadCount]; |
|
||||
var size = count / actions.Length; |
|
||||
|
|
||||
// partition the jobs into separate sets for each but the last worked thread
|
|
||||
for (var i = 0; i < actions.Length - 1; i++) |
|
||||
{ |
|
||||
var start = fromInclusive + (i * size); |
|
||||
var stop = fromInclusive + ((i + 1) * size); |
|
||||
|
|
||||
actions[i] = |
|
||||
() => |
|
||||
{ |
|
||||
for (int j = start; j < stop; j++) |
|
||||
{ |
|
||||
body(j); |
|
||||
} |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
// add another set for last worker thread
|
|
||||
actions[actions.Length - 1] = |
|
||||
() => |
|
||||
{ |
|
||||
for (int i = fromInclusive + ((actions.Length - 1) * size); i < toExclusive; i++) |
|
||||
{ |
|
||||
body(i); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
Invoke(actions); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Executes a for loop in which iterations may run in parallel.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="T">The type of the thread-local data.</typeparam>
|
|
||||
/// <param name="fromInclusive">The start index, inclusive.</param>
|
|
||||
/// <param name="toExclusive">The end index, exclusive.</param>
|
|
||||
/// <param name="localInit">The function delegate that returns the initial state of the local data for each thread.</param>
|
|
||||
/// <param name="body">The delegate that is invoked once per iteration.</param>
|
|
||||
/// <param name="localFinally">The delegate that performs a final action on the local state of each thread.</param>
|
|
||||
public static void For<T>(int fromInclusive, int toExclusive, Func<T> localInit, Func<int, T, T> body, Action<T> localFinally) |
|
||||
{ |
|
||||
var count = toExclusive - fromInclusive; |
|
||||
var tasks = new Task<T>[ThreadQueue.ThreadCount]; |
|
||||
var size = count / tasks.Length; |
|
||||
|
|
||||
// fast forward execution if it's only one or none items
|
|
||||
if (count <= 1) |
|
||||
{ |
|
||||
if (count == 1) |
|
||||
{ |
|
||||
localFinally(body(fromInclusive, localInit())); |
|
||||
} |
|
||||
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// fast forward execution in case parallelization is disabled
|
|
||||
if (Control.DisableParallelization |
|
||||
|| ThreadQueue.ThreadCount <= 1 |
|
||||
|| ThreadQueue.IsInWorkerThread) |
|
||||
{ |
|
||||
var localresult = localInit(); |
|
||||
for (var i = fromInclusive; i < toExclusive; i++) |
|
||||
{ |
|
||||
localresult = body(i, localresult); |
|
||||
} |
|
||||
|
|
||||
localFinally(localresult); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// partition the jobs into separate sets for each but the last worked thread
|
|
||||
for (var i = 0; i < tasks.Length - 1; i++) |
|
||||
{ |
|
||||
var start = fromInclusive + (i * size); |
|
||||
var stop = fromInclusive + ((i + 1) * size); |
|
||||
tasks[i] = new Task<T>( |
|
||||
localData => |
|
||||
{ |
|
||||
var localresult = (T)localData; |
|
||||
for (var j = start; j < stop; j++) |
|
||||
{ |
|
||||
localresult = body(j, localresult); |
|
||||
} |
|
||||
|
|
||||
return localresult; |
|
||||
}, |
|
||||
localInit()); |
|
||||
ThreadQueue.Enqueue(tasks[i]); |
|
||||
} |
|
||||
|
|
||||
// add another set for last worker thread
|
|
||||
tasks[tasks.Length - 1] = new Task<T>( |
|
||||
localData => |
|
||||
{ |
|
||||
var localresult = (T)localData; |
|
||||
for (var i = fromInclusive + ((tasks.Length - 1) * size); i < toExclusive; i++) |
|
||||
{ |
|
||||
localresult = body(i, localresult); |
|
||||
} |
|
||||
|
|
||||
return localresult; |
|
||||
}, |
|
||||
localInit()); |
|
||||
|
|
||||
ThreadQueue.Enqueue(tasks[tasks.Length - 1]); |
|
||||
if (tasks.Length <= 0) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
WaitForTasksToComplete(tasks); |
|
||||
|
|
||||
foreach (var t in tasks) |
|
||||
{ |
|
||||
localFinally(t.Result); |
|
||||
} |
|
||||
|
|
||||
CollectExceptions(tasks); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Executes a for each operation on an IEnumerable{T} in which iterations may run in parallel.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="T">The type of the data in the source.</typeparam>
|
|
||||
/// <param name="source">An enumerable data source.</param>
|
|
||||
/// <param name="body">The delegate that is invoked once per iteration.</param>
|
|
||||
public static void ForEach<T>(IEnumerable<T> source, Action<T> body) |
|
||||
{ |
|
||||
if (body == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("body"); |
|
||||
} |
|
||||
|
|
||||
// fast forward execution in case parallelization is disabled
|
|
||||
if (Control.DisableParallelization |
|
||||
|| ThreadQueue.ThreadCount <= 1 |
|
||||
|| ThreadQueue.IsInWorkerThread) |
|
||||
{ |
|
||||
foreach (var item in source) |
|
||||
{ |
|
||||
body(item); |
|
||||
} |
|
||||
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// source is a IList, call For instead.
|
|
||||
if (source is IList<T>) |
|
||||
{ |
|
||||
var list = (IList<T>)source; |
|
||||
For(0, list.Count, i => body(list[i])); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var maxBlockSize = IntialBlockSize; |
|
||||
var tasks = new List<Task>(); |
|
||||
|
|
||||
var enumerator = source.GetEnumerator(); |
|
||||
while (enumerator.MoveNext()) |
|
||||
{ |
|
||||
var pos = 0; |
|
||||
var list = new T[maxBlockSize]; |
|
||||
list[pos++] = enumerator.Current; |
|
||||
|
|
||||
var count = 1; |
|
||||
while (count < maxBlockSize && enumerator.MoveNext()) |
|
||||
{ |
|
||||
list[pos++] = enumerator.Current; |
|
||||
count++; |
|
||||
} |
|
||||
|
|
||||
var task = new Task( |
|
||||
() => |
|
||||
{ |
|
||||
for (var i = 0; i < pos; i++) |
|
||||
{ |
|
||||
body(list[i]); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
ThreadQueue.Enqueue(task); |
|
||||
tasks.Add(task); |
|
||||
maxBlockSize = Math.Min(MaxBlockSize, maxBlockSize * ScalingFactor); |
|
||||
} |
|
||||
|
|
||||
if (tasks.Count > 0) |
|
||||
{ |
|
||||
WaitForTasksToComplete(tasks.ToArray()); |
|
||||
CollectExceptions(tasks); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Executes a for each operation on an IEnumerable{TSource in which iterations may run in parallel.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TSource">The type of the data in the source.</typeparam>
|
|
||||
/// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
|
|
||||
/// <param name="source">An enumerable data source.</param>
|
|
||||
/// <param name="localInit">The function delegate that returns the initial state of the local data for each thread.</param>
|
|
||||
/// <param name="body">The delegate that is invoked once per iteration.</param>
|
|
||||
/// <param name="localFinally">The delegate that performs a final action on the local state of each thread.</param>
|
|
||||
public static void ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> localInit, Func<TSource, TLocal, TLocal> body, Action<TLocal> localFinally) |
|
||||
{ |
|
||||
if (body == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("body"); |
|
||||
} |
|
||||
|
|
||||
// fast forward execution in case parallelization is disabled
|
|
||||
if (Control.DisableParallelization |
|
||||
|| ThreadQueue.ThreadCount <= 1 |
|
||||
|| ThreadQueue.IsInWorkerThread) |
|
||||
{ |
|
||||
var localResult = localInit(); |
|
||||
foreach (var item in source) |
|
||||
{ |
|
||||
localResult = body(item, localResult); |
|
||||
} |
|
||||
|
|
||||
localFinally(localResult); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// source is a IList, call For instead.
|
|
||||
if (source is IList<TSource>) |
|
||||
{ |
|
||||
var list = (IList<TSource>)source; |
|
||||
For(0, list.Count, localInit, (i, local) => body(list[i], local), localFinally); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var maxBlockSize = IntialBlockSize; |
|
||||
var tasks = new List<Task<TLocal>>(); |
|
||||
|
|
||||
var enumerator = source.GetEnumerator(); |
|
||||
while (enumerator.MoveNext()) |
|
||||
{ |
|
||||
var pos = 0; |
|
||||
var list = new TSource[maxBlockSize]; |
|
||||
list[pos++] = enumerator.Current; |
|
||||
|
|
||||
var count = 1; |
|
||||
while (count < maxBlockSize && enumerator.MoveNext()) |
|
||||
{ |
|
||||
list[pos++] = enumerator.Current; |
|
||||
count++; |
|
||||
} |
|
||||
|
|
||||
var task = new Task<TLocal>( |
|
||||
localData => |
|
||||
{ |
|
||||
var localresult = localData; |
|
||||
for (var i = 0; i < pos; i++) |
|
||||
{ |
|
||||
localresult = body(list[i], (TLocal)localresult); |
|
||||
} |
|
||||
|
|
||||
return (TLocal)localresult; |
|
||||
}, |
|
||||
localInit()); |
|
||||
|
|
||||
ThreadQueue.Enqueue(task); |
|
||||
tasks.Add(task); |
|
||||
maxBlockSize = Math.Min(MaxBlockSize, maxBlockSize * ScalingFactor); |
|
||||
} |
|
||||
|
|
||||
if (tasks.Count <= 0) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var taskArray = tasks.ToArray(); |
|
||||
WaitForTasksToComplete(taskArray); |
|
||||
|
|
||||
for (var i = 0; i < taskArray.Length; i++) |
|
||||
{ |
|
||||
localFinally(tasks[i].Result); |
|
||||
} |
|
||||
|
|
||||
CollectExceptions(taskArray); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Executes each of the provided actions inside a discrete, asynchronous task.
|
|
||||
/// </summary>
|
|
||||
/// <param name="actions">An array of actions to execute.</param>
|
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="actions"/> argument is null.</exception>
|
|
||||
/// <exception cref="ArgumentException">The actions array contains a null element.</exception>
|
|
||||
/// <exception cref="AggregateException">An action threw an exception.</exception>
|
|
||||
public static void Run(params Action[] actions) |
|
||||
{ |
|
||||
if (actions == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("actions"); |
|
||||
} |
|
||||
|
|
||||
// fast forward execution if it's only one or none items
|
|
||||
if (actions.Length <= 1) |
|
||||
{ |
|
||||
if (actions.Length == 1) |
|
||||
{ |
|
||||
actions[0](); |
|
||||
} |
|
||||
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// fast forward execution in case parallelization is disabled
|
|
||||
if (Control.DisableParallelization |
|
||||
|| ThreadQueue.ThreadCount <= 1 |
|
||||
|| ThreadQueue.IsInWorkerThread) |
|
||||
{ |
|
||||
for (var i = 0; i < actions.Length; i++) |
|
||||
{ |
|
||||
actions[i](); |
|
||||
} |
|
||||
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
Invoke(actions); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Executes each of the provided actions inside a discrete, asynchronous task.
|
|
||||
/// </summary>
|
|
||||
/// <param name="actions">An array of actions to execute.</param>
|
|
||||
/// <exception cref="ArgumentException">The actions array contains a null element.</exception>
|
|
||||
/// <exception cref="AggregateException">An action threw an exception.</exception>
|
|
||||
internal static void Invoke(params Action[] actions) |
|
||||
{ |
|
||||
// create a job for each action
|
|
||||
var tasks = new Task[actions.Length]; |
|
||||
for (var i = 0; i < tasks.Length; i++) |
|
||||
{ |
|
||||
Action action = actions[i]; |
|
||||
if (action == null) |
|
||||
{ |
|
||||
throw new ArgumentException(String.Format(Resources.ArgumentItemNull, "actions"), "actions"); |
|
||||
} |
|
||||
|
|
||||
tasks[i] = new Task(action); |
|
||||
} |
|
||||
|
|
||||
// run the jobs
|
|
||||
ThreadQueue.Enqueue(tasks); |
|
||||
|
|
||||
WaitForTasksToComplete(tasks); |
|
||||
|
|
||||
CollectExceptions(tasks); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Waits for tasks to complete.
|
|
||||
/// </summary>
|
|
||||
/// <param name="tasks">The tasks.</param>
|
|
||||
private static void WaitForTasksToComplete(Task[] tasks) |
|
||||
{ |
|
||||
foreach (var task in tasks) |
|
||||
{ |
|
||||
task.Wait(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Collects the exceptions and dispose tasks.
|
|
||||
/// </summary>
|
|
||||
/// <param name="tasks">The tasks.</param>
|
|
||||
private static void CollectExceptions(IEnumerable<Task> tasks) |
|
||||
{ |
|
||||
// collect all thrown exceptions and dispose the jobs
|
|
||||
var exceptions = new List<Exception>(); |
|
||||
foreach (var task in tasks) |
|
||||
{ |
|
||||
if (task.IsFaulted) |
|
||||
{ |
|
||||
exceptions.Add(task.Exception); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// throw the aggregated exceptions, if any
|
|
||||
if (exceptions.Count > 0) |
|
||||
{ |
|
||||
throw new AggregateException(exceptions); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,128 +0,0 @@ |
|||||
// <copyright file="Task.cs" company="Math.NET">
|
|
||||
// Math.NET Numerics, part of the Math.NET Project
|
|
||||
// http://mathnet.opensourcedotnet.info
|
|
||||
//
|
|
||||
// Copyright (c) 2009 Math.NET
|
|
||||
//
|
|
||||
// Permission is hereby granted, free of charge, to any person
|
|
||||
// obtaining a copy of this software and associated documentation
|
|
||||
// files (the "Software"), to deal in the Software without
|
|
||||
// restriction, including without limitation the rights to use,
|
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||
// copies of the Software, and to permit persons to whom the
|
|
||||
// Software is furnished to do so, subject to the following
|
|
||||
// conditions:
|
|
||||
//
|
|
||||
// The above copyright notice and this permission notice shall be
|
|
||||
// included in all copies or substantial portions of the Software.
|
|
||||
//
|
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace MathNet.Numerics.Threading |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Threading; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Internal Parallel Task Handle.
|
|
||||
/// </summary>
|
|
||||
internal class Task |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Delegate to the task's action.
|
|
||||
/// </summary>
|
|
||||
private readonly System.Action _body; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the Task class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="body">Delegate to the task's action.</param>
|
|
||||
public Task(Action body) |
|
||||
{ |
|
||||
if (body == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("body"); |
|
||||
} |
|
||||
|
|
||||
_body = body; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="Task"/> class.
|
|
||||
/// </summary>
|
|
||||
protected Task() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether the task completed due to an unhandled exception.
|
|
||||
/// </summary>
|
|
||||
/// <value>
|
|
||||
/// <c>true</c> if this task completed due to an unhandled exception; otherwise, <c>false</c>.
|
|
||||
/// </value>
|
|
||||
public bool IsFaulted |
|
||||
{ |
|
||||
get { return Exception != null; } |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether this task has completed.
|
|
||||
/// </summary>
|
|
||||
/// <value>
|
|
||||
/// <c>true</c> if this task has completed; otherwise, <c>false</c>.
|
|
||||
/// </value>
|
|
||||
public bool IsCompleted |
|
||||
{ |
|
||||
get; |
|
||||
private set; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets the exception thrown by the task, if any.
|
|
||||
/// </summary>
|
|
||||
public Exception Exception { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Run the task.
|
|
||||
/// </summary>
|
|
||||
public void Compute() |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
DoCompute(); |
|
||||
IsCompleted = true; |
|
||||
} |
|
||||
catch (Exception e) |
|
||||
{ |
|
||||
Exception = e; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Runs the actual task.
|
|
||||
/// </summary>
|
|
||||
protected virtual void DoCompute() |
|
||||
{ |
|
||||
_body(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Waits for the task to complete execution.
|
|
||||
/// </summary>
|
|
||||
public void Wait() |
|
||||
{ |
|
||||
while (!IsCompleted && !IsFaulted) |
|
||||
{ |
|
||||
Thread.Sleep(0); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,79 +0,0 @@ |
|||||
// <copyright file="TaskOfT.cs" company="Math.NET">
|
|
||||
// Math.NET Numerics, part of the Math.NET Project
|
|
||||
// http://mathnet.opensourcedotnet.info
|
|
||||
//
|
|
||||
// Copyright (c) 2009 Math.NET
|
|
||||
//
|
|
||||
// Permission is hereby granted, free of charge, to any person
|
|
||||
// obtaining a copy of this software and associated documentation
|
|
||||
// files (the "Software"), to deal in the Software without
|
|
||||
// restriction, including without limitation the rights to use,
|
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||
// copies of the Software, and to permit persons to whom the
|
|
||||
// Software is furnished to do so, subject to the following
|
|
||||
// conditions:
|
|
||||
//
|
|
||||
// The above copyright notice and this permission notice shall be
|
|
||||
// included in all copies or substantial portions of the Software.
|
|
||||
//
|
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace MathNet.Numerics.Threading |
|
||||
{ |
|
||||
using System; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Internal Generic Parallel Task Handle.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TResult">The type of the result.</typeparam>
|
|
||||
internal class Task<TResult> : Task |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Delegate to the task's action.
|
|
||||
/// </summary>
|
|
||||
private readonly Func<object, TResult> _body; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Variable used to hold state information between iterations.
|
|
||||
/// </summary>
|
|
||||
private readonly object _state; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the result of the task.
|
|
||||
/// </summary>
|
|
||||
/// <value>The result of the task.</value>
|
|
||||
public TResult Result { get; private set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the Task class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="body">Delegate to the task's action.</param>
|
|
||||
/// <param name="state">An object representing data to be used by the action.</param>
|
|
||||
public Task(Func<object, TResult> body, object state) |
|
||||
{ |
|
||||
if (body == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("body"); |
|
||||
} |
|
||||
|
|
||||
_state = state; |
|
||||
_body = body; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Runs the actual task.
|
|
||||
/// </summary>
|
|
||||
protected override void DoCompute() |
|
||||
{ |
|
||||
Result = _body(_state); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,258 +0,0 @@ |
|||||
// <copyright file="ThreadQueue.cs" company="Math.NET">
|
|
||||
// Math.NET Numerics, part of the Math.NET Project
|
|
||||
// http://mathnet.opensourcedotnet.info
|
|
||||
//
|
|
||||
// Copyright (c) 2009 Math.NET
|
|
||||
//
|
|
||||
// Permission is hereby granted, free of charge, to any person
|
|
||||
// obtaining a copy of this software and associated documentation
|
|
||||
// files (the "Software"), to deal in the Software without
|
|
||||
// restriction, including without limitation the rights to use,
|
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||
// copies of the Software, and to permit persons to whom the
|
|
||||
// Software is furnished to do so, subject to the following
|
|
||||
// conditions:
|
|
||||
//
|
|
||||
// The above copyright notice and this permission notice shall be
|
|
||||
// included in all copies or substantial portions of the Software.
|
|
||||
//
|
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace MathNet.Numerics.Threading |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Internal Parallel Thread Queue.
|
|
||||
/// </summary>
|
|
||||
internal static class ThreadQueue |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Sync Object for the thread queue state.
|
|
||||
/// </summary>
|
|
||||
private static readonly object _stateSync = new object(); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Sync Object for queue access (to be sure it's used by us only).
|
|
||||
/// </summary>
|
|
||||
private static readonly object _queueSync = new object(); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Queue holding the pending jobs.
|
|
||||
/// </summary>
|
|
||||
private static readonly Queue<Task> _queue = new Queue<Task>(); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Running flag, used to signal worker threads to stop cleanly.
|
|
||||
/// </summary>
|
|
||||
private static bool _running = true; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Worker threads
|
|
||||
/// </summary>
|
|
||||
private static Thread[] _threads; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the number of worker threads.
|
|
||||
/// </summary>
|
|
||||
internal static int ThreadCount { get; private set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Indicating whether the current thread is a parallelized worker thread.
|
|
||||
/// </summary>
|
|
||||
[ThreadStatic] |
|
||||
private static bool _isInWorkerThread; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes static members of the ThreadQueue class.
|
|
||||
/// </summary>
|
|
||||
static ThreadQueue() |
|
||||
{ |
|
||||
Start(1); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value indicating whether the current thread is a parallelized worker thread.
|
|
||||
/// </summary>
|
|
||||
public static bool IsInWorkerThread |
|
||||
{ |
|
||||
get { return _isInWorkerThread; } |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Add a job to the queue.
|
|
||||
/// </summary>
|
|
||||
/// <param name="task">The job to run.</param>
|
|
||||
public static void Enqueue(Task task) |
|
||||
{ |
|
||||
if (!_running) |
|
||||
{ |
|
||||
Start(); |
|
||||
} |
|
||||
|
|
||||
lock (_queueSync) |
|
||||
{ |
|
||||
_queue.Enqueue(task); |
|
||||
Monitor.Pulse(_queueSync); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Add a set of jobs to the queue.
|
|
||||
/// </summary>
|
|
||||
/// <param name="tasks">The jobs to run.</param>
|
|
||||
public static void Enqueue(IList<Task> tasks) |
|
||||
{ |
|
||||
if (!_running) |
|
||||
{ |
|
||||
Start(); |
|
||||
} |
|
||||
|
|
||||
lock (_queueSync) |
|
||||
{ |
|
||||
foreach (var task in tasks) |
|
||||
{ |
|
||||
_queue.Enqueue(task); |
|
||||
} |
|
||||
|
|
||||
Monitor.PulseAll(_queueSync); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Worker Thread Program
|
|
||||
/// </summary>
|
|
||||
private static void WorkerThreadStart() |
|
||||
{ |
|
||||
_isInWorkerThread = true; |
|
||||
|
|
||||
while (_running) |
|
||||
{ |
|
||||
// Get the job...
|
|
||||
Task task = null; |
|
||||
|
|
||||
lock (_queueSync) |
|
||||
{ |
|
||||
// Check whether we should shut down
|
|
||||
if (!_running) |
|
||||
{ |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
if (_queue.Count > 0) |
|
||||
{ |
|
||||
task = _queue.Dequeue(); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
Monitor.Wait(_queueSync); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (task == null) |
|
||||
{ |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
// ...and run it
|
|
||||
task.Compute(); |
|
||||
} |
|
||||
|
|
||||
_isInWorkerThread = false; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Start or restart the queue with the specified number of worker threads.
|
|
||||
/// </summary>
|
|
||||
/// <param name="numberOfThreads">Number of worker threads.</param>
|
|
||||
public static void Start(int numberOfThreads) |
|
||||
{ |
|
||||
lock (_stateSync) |
|
||||
{ |
|
||||
// instead of throwing an out of range exception, simply normalize
|
|
||||
numberOfThreads = Math.Max(1, Math.Min(1024, numberOfThreads)); |
|
||||
|
|
||||
if (_threads != null) |
|
||||
{ |
|
||||
if (_threads.Length == numberOfThreads) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
Shutdown(); |
|
||||
} |
|
||||
|
|
||||
ThreadCount = numberOfThreads; |
|
||||
Start(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Start the thread queue, if it is not already running.
|
|
||||
/// </summary>
|
|
||||
public static void Start() |
|
||||
{ |
|
||||
lock (_stateSync) |
|
||||
{ |
|
||||
if (_threads != null) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
_running = true; |
|
||||
|
|
||||
_threads = new Thread[ThreadCount]; |
|
||||
|
|
||||
for (var i = 0; i < _threads.Length; i++) |
|
||||
{ |
|
||||
_threads[i] = new Thread(WorkerThreadStart) |
|
||||
{ |
|
||||
IsBackground = true |
|
||||
}; |
|
||||
|
|
||||
_threads[i].Start(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Stop the thread queue, if it is running.
|
|
||||
/// </summary>
|
|
||||
public static void Shutdown() |
|
||||
{ |
|
||||
// try to stop the worker threads cleanly
|
|
||||
lock (_stateSync) |
|
||||
{ |
|
||||
if (_threads == null) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
_running = false; |
|
||||
|
|
||||
lock (_queueSync) |
|
||||
{ |
|
||||
Monitor.PulseAll(_queueSync); |
|
||||
} |
|
||||
|
|
||||
// wait until all threads have stopped
|
|
||||
foreach (var thread in _threads) |
|
||||
{ |
|
||||
thread.Join(); |
|
||||
} |
|
||||
|
|
||||
_threads = null; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue