Found some more remaining traces of Microsoft's scrapyard and killed them; removed WinRT support
git-svn-id: file:///srv/devel/repo-conversion/nusu@315 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
b1b1f02e6f
commit
b6fe183994
|
@ -276,10 +276,6 @@
|
||||||
<Compile Include="Source\TypeHelper.Test.cs">
|
<Compile Include="Source\TypeHelper.Test.cs">
|
||||||
<DependentUpon>TypeHelper.cs</DependentUpon>
|
<DependentUpon>TypeHelper.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Source\Semaphore.cs" />
|
|
||||||
<Compile Include="Source\Semaphore.Test.cs">
|
|
||||||
<DependentUpon>Semaphore.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Source\FloatHelper.cs" />
|
<Compile Include="Source\FloatHelper.cs" />
|
||||||
<Compile Include="Source\FloatHelper.Test.cs">
|
<Compile Include="Source\FloatHelper.Test.cs">
|
||||||
<DependentUpon>FloatHelper.cs</DependentUpon>
|
<DependentUpon>FloatHelper.cs</DependentUpon>
|
||||||
|
@ -309,9 +305,6 @@
|
||||||
<DependentUpon>StringSegment.cs</DependentUpon>
|
<DependentUpon>StringSegment.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Source\WeakReference.cs" />
|
<Compile Include="Source\WeakReference.cs" />
|
||||||
<Compile Include="Source\WeakReference.Phone7.cs">
|
|
||||||
<DependentUpon>WeakReference.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Source\WeakReference.Test.cs">
|
<Compile Include="Source\WeakReference.Test.cs">
|
||||||
<DependentUpon>WeakReference.cs</DependentUpon>
|
<DependentUpon>WeakReference.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -21,7 +21,7 @@ using System.Runtime.InteropServices;
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("1308e4c3-a0c1-423a-aaae-61c7314777e0")]
|
[assembly: Guid("1308e4c3-a0c1-423a-aaae-61c7314777e0")]
|
||||||
|
|
||||||
#if !(WINDOWS_PHONE || XBOX360) && UNITTEST
|
#if UNITTEST
|
||||||
// This is required to NMock can derive its proxies from interfaces in
|
// This is required to NMock can derive its proxies from interfaces in
|
||||||
// the internal unit test classes
|
// the internal unit test classes
|
||||||
[assembly: InternalsVisibleTo(NMock.Constants.InternalsVisibleToDynamicProxy)]
|
[assembly: InternalsVisibleTo(NMock.Constants.InternalsVisibleToDynamicProxy)]
|
||||||
|
|
|
@ -49,11 +49,7 @@ namespace Nuclex.Support {
|
||||||
public static class AffineThreadPool {
|
public static class AffineThreadPool {
|
||||||
|
|
||||||
/// <summary>Number of CPU cores available on the system</summary>
|
/// <summary>Number of CPU cores available on the system</summary>
|
||||||
#if XBOX360
|
|
||||||
public static readonly int Processors = 4;
|
|
||||||
#else
|
|
||||||
public static readonly int Processors = Environment.ProcessorCount;
|
public static readonly int Processors = Environment.ProcessorCount;
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>Delegate used by the thread pool to report unhandled exceptions</summary>
|
/// <summary>Delegate used by the thread pool to report unhandled exceptions</summary>
|
||||||
/// <param name="exception">Exception that has not been handled</param>
|
/// <param name="exception">Exception that has not been handled</param>
|
||||||
|
@ -88,25 +84,16 @@ namespace Nuclex.Support {
|
||||||
// as we may run into situations where multiple operations need to be atomic.
|
// as we may run into situations where multiple operations need to be atomic.
|
||||||
// We keep track of the threads we've created just for good measure; not actually
|
// We keep track of the threads we've created just for good measure; not actually
|
||||||
// needed for any core functionality.
|
// needed for any core functionality.
|
||||||
#if XBOX360 || WINDOWS_PHONE
|
|
||||||
workAvailable = new Semaphore();
|
|
||||||
#else
|
|
||||||
workAvailable = new System.Threading.Semaphore(0, int.MaxValue);
|
workAvailable = new System.Threading.Semaphore(0, int.MaxValue);
|
||||||
#endif
|
|
||||||
userWorkItems = new Queue<UserWorkItem>(Processors * 4);
|
userWorkItems = new Queue<UserWorkItem>(Processors * 4);
|
||||||
workerThreads = new List<Thread>(Processors);
|
workerThreads = new List<Thread>(Processors);
|
||||||
inUseThreads = 0;
|
inUseThreads = 0;
|
||||||
|
|
||||||
#if XBOX360
|
|
||||||
// We can only use these hardware thread indices on the XBox 360
|
|
||||||
hardwareThreads = new Queue<int>(new int[] { 5, 4, 3, 1 });
|
|
||||||
#else
|
|
||||||
// We can use all cores on a PC, starting from index 1
|
// We can use all cores on a PC, starting from index 1
|
||||||
hardwareThreads = new Queue<int>(Processors);
|
hardwareThreads = new Queue<int>(Processors);
|
||||||
for(int core = Processors; core >= 1; --core) {
|
for(int core = Processors; core >= 1; --core) {
|
||||||
hardwareThreads.Enqueue(core);
|
hardwareThreads.Enqueue(core);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create all of the worker threads
|
// Create all of the worker threads
|
||||||
for(int index = 0; index < Processors; index++) {
|
for(int index = 0; index < Processors; index++) {
|
||||||
|
@ -211,12 +198,7 @@ namespace Nuclex.Support {
|
||||||
hardwareThreadIndex = hardwareThreads.Dequeue();
|
hardwareThreadIndex = hardwareThreads.Dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if XBOX360
|
#if WINDOWS
|
||||||
// On the XBox 360, the only way to get a thread to run on another core is to
|
|
||||||
// explicitly move it to that core. MSDN states that SetProcessorAffinity() should
|
|
||||||
// be called from the thread whose affinity is being changed.
|
|
||||||
Thread.CurrentThread.SetProcessorAffinity(new int[] { hardwareThreadIndex });
|
|
||||||
#elif WINDOWS
|
|
||||||
if(Environment.OSVersion.Platform == PlatformID.Win32NT) {
|
if(Environment.OSVersion.Platform == PlatformID.Win32NT) {
|
||||||
// Prevent this managed thread from impersonating another system thread.
|
// Prevent this managed thread from impersonating another system thread.
|
||||||
// In .NET, managed threads can supposedly be moved to different system threads
|
// In .NET, managed threads can supposedly be moved to different system threads
|
||||||
|
@ -303,11 +285,7 @@ namespace Nuclex.Support {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to let the threads in the thread pool wait for new work to appear.
|
/// Used to let the threads in the thread pool wait for new work to appear.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if XBOX360 || WINDOWS_PHONE
|
|
||||||
private static Semaphore workAvailable;
|
|
||||||
#else
|
|
||||||
private static System.Threading.Semaphore workAvailable;
|
private static System.Threading.Semaphore workAvailable;
|
||||||
#endif
|
|
||||||
/// <summary>List of all worker threads at the disposal of the thread pool.</summary>
|
/// <summary>List of all worker threads at the disposal of the thread pool.</summary>
|
||||||
private static List<Thread> workerThreads;
|
private static List<Thread> workerThreads;
|
||||||
/// <summary>Number of threads currently active.</summary>
|
/// <summary>Number of threads currently active.</summary>
|
||||||
|
|
|
@ -161,11 +161,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// <returns>A clone of the original instance</returns>
|
/// <returns>A clone of the original instance</returns>
|
||||||
private static object shallowCloneComplexFieldBased(object original) {
|
private static object shallowCloneComplexFieldBased(object original) {
|
||||||
Type originalType = original.GetType();
|
Type originalType = original.GetType();
|
||||||
#if (XBOX360 || WINDOWS_PHONE)
|
|
||||||
object clone = Activator.CreateInstance(originalType);
|
|
||||||
#else
|
|
||||||
object clone = FormatterServices.GetUninitializedObject(originalType);
|
object clone = FormatterServices.GetUninitializedObject(originalType);
|
||||||
#endif
|
|
||||||
|
|
||||||
FieldInfo[] fieldInfos = originalType.GetFieldInfosIncludingBaseClasses(
|
FieldInfo[] fieldInfos = originalType.GetFieldInfosIncludingBaseClasses(
|
||||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
|
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
|
||||||
|
@ -243,11 +239,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// <returns>A clone of the original instance</returns>
|
/// <returns>A clone of the original instance</returns>
|
||||||
private static object deepCloneComplexFieldBased(object original) {
|
private static object deepCloneComplexFieldBased(object original) {
|
||||||
Type originalType = original.GetType();
|
Type originalType = original.GetType();
|
||||||
#if (XBOX360 || WINDOWS_PHONE)
|
|
||||||
object clone = Activator.CreateInstance(originalType);
|
|
||||||
#else
|
|
||||||
object clone = FormatterServices.GetUninitializedObject(originalType);
|
object clone = FormatterServices.GetUninitializedObject(originalType);
|
||||||
#endif
|
|
||||||
|
|
||||||
FieldInfo[] fieldInfos = originalType.GetFieldInfosIncludingBaseClasses(
|
FieldInfo[] fieldInfos = originalType.GetFieldInfosIncludingBaseClasses(
|
||||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
|
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
|
||||||
|
|
|
@ -18,8 +18,6 @@ License along with this library
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#if !(XBOX360 || WINDOWS_PHONE)
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -328,5 +326,3 @@ namespace Nuclex.Support.Cloning {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Nuclex.Support.Cloning
|
} // namespace Nuclex.Support.Cloning
|
||||||
|
|
||||||
#endif // !(XBOX360 || WINDOWS_PHONE)
|
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
#region CPL License
|
||||||
|
/*
|
||||||
|
Nuclex Framework
|
||||||
|
Copyright (C) 2002-2014 Nuclex Development Labs
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the IBM Common Public License as
|
||||||
|
published by the IBM Corporation; either version 1.0 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
IBM Common Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the IBM Common Public
|
||||||
|
License along with this library
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
#if !NO_CONCURRENT_COLLECTIONS
|
#if !NO_CONCURRENT_COLLECTIONS
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
@ -13,11 +33,7 @@ namespace Nuclex.Support {
|
||||||
public abstract class ParallelBackgroundWorker<TTask> : IDisposable {
|
public abstract class ParallelBackgroundWorker<TTask> : IDisposable {
|
||||||
|
|
||||||
/// <summary>Number of CPU cores available on the system</summary>
|
/// <summary>Number of CPU cores available on the system</summary>
|
||||||
#if XBOX360
|
|
||||||
public static readonly int Processors = 4;
|
|
||||||
#else
|
|
||||||
public static readonly int Processors = Environment.ProcessorCount;
|
public static readonly int Processors = Environment.ProcessorCount;
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout after which Dispose() will stop waiting for unfinished tasks and
|
/// Timeout after which Dispose() will stop waiting for unfinished tasks and
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
#region CPL License
|
|
||||||
/*
|
|
||||||
Nuclex Framework
|
|
||||||
Copyright (C) 2002-2014 Nuclex Development Labs
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the IBM Common Public License as
|
|
||||||
published by the IBM Corporation; either version 1.0 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
IBM Common Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the IBM Common Public
|
|
||||||
License along with this library
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#if UNITTEST
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Nuclex.Support {
|
|
||||||
|
|
||||||
/// <summary>Unit Test for the Semaphore class</summary>
|
|
||||||
[
|
|
||||||
TestFixture,
|
|
||||||
Obsolete("Not obsolete, prevents warning when unit-testing custom Semaphore on Windows")
|
|
||||||
]
|
|
||||||
internal class SemaphoreTest {
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Test whether a semaphore can be initialized with reverse counting
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestReverseCountingConstructor() {
|
|
||||||
using(Semaphore semaphore = new Semaphore()) {
|
|
||||||
Assert.IsNotNull(semaphore); // nonsense, avoids compiler warning
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Test whether a semaphore can be initialized with a maximum user count
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestLimitConstructor() {
|
|
||||||
using(Semaphore semaphore = new Semaphore(16)) {
|
|
||||||
Assert.IsNotNull(semaphore); // nonsense, avoids compiler warning
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Test whether a semaphore can be initialized with an initial user
|
|
||||||
/// count and a maximum user count
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestFullConstructor() {
|
|
||||||
using(Semaphore semaphore = new Semaphore(8, 16)) {
|
|
||||||
Assert.IsNotNull(semaphore); // nonsense, avoids compiler warning
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Verifies that the right exception is thrown if a semaphore is initialized
|
|
||||||
/// with a larger number of initial users than the maximum number of users.
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestThrowOnMoreInitialUsersThanMaximumUsers() {
|
|
||||||
Assert.Throws<ArgumentOutOfRangeException>(
|
|
||||||
delegate() {
|
|
||||||
Semaphore semaphore = new Semaphore(2, 1);
|
|
||||||
semaphore.Close();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Verifies that the semaphore can time out if the resource does not become
|
|
||||||
/// available within the time limit specified by the user
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestWaitTimeout() {
|
|
||||||
using(Semaphore semaphore = new Semaphore(1)) {
|
|
||||||
Assert.IsTrue(semaphore.WaitOne(1000));
|
|
||||||
Assert.IsFalse(semaphore.WaitOne(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Verifies that the semaphore can time out if the resource does not become
|
|
||||||
/// available within the time limit specified by the user, if the time limit
|
|
||||||
/// is specified using the TimeSpan class
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestWaitTimeoutWithTimeSpan() {
|
|
||||||
using(Semaphore semaphore = new Semaphore(1)) {
|
|
||||||
Assert.IsTrue(semaphore.WaitOne(TimeSpan.FromSeconds(1)));
|
|
||||||
Assert.IsFalse(semaphore.WaitOne(TimeSpan.FromSeconds(0)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tests whether an exception is thrown if the WaitOne() method is called
|
|
||||||
/// with a time span that is too large for the underlying synchronization API
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void TestThrowOnWaitWithTooLargeTimeSpan() {
|
|
||||||
using(Semaphore semaphore = new Semaphore(1)) {
|
|
||||||
Assert.Throws<ArgumentOutOfRangeException>(
|
|
||||||
delegate() {
|
|
||||||
semaphore.WaitOne(TimeSpan.FromMilliseconds(1L << 32));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Nuclex.Support
|
|
||||||
|
|
||||||
#endif // UNITTEST
|
|
|
@ -1,248 +0,0 @@
|
||||||
#region CPL License
|
|
||||||
/*
|
|
||||||
Nuclex Framework
|
|
||||||
Copyright (C) 2002-2014 Nuclex Development Labs
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the IBM Common Public License as
|
|
||||||
published by the IBM Corporation; either version 1.0 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
IBM Common Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the IBM Common Public
|
|
||||||
License along with this library
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Nuclex.Support {
|
|
||||||
|
|
||||||
/// <summary>A reverse counting semaphore</summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// This semaphore counts in reverse, which means you can Release() the semaphore
|
|
||||||
/// as often as you'd like a thread calling WaitOne() to be let through. You
|
|
||||||
/// can use it in the traditional sense and have any Thread calling WaitOne()
|
|
||||||
/// make sure to call Release() afterwards, or you can, for example, Release() it
|
|
||||||
/// whenever work becomes available and let threads take work from the Semaphore
|
|
||||||
/// by calling WaitOne() alone.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// Implementation notes (ignore this if you just want to use the Semaphore)
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// We could design a semaphore that uses an auto reset event, where the thread
|
|
||||||
/// that gets to pass immediately sets the event again if the semaphore isn't full
|
|
||||||
/// yet to let another thread pass.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// However, this would mean that when a semaphore receives a large number of
|
|
||||||
/// wait requests, assuming it would allow, for example, 25 users at once, the
|
|
||||||
/// thread scheduler would see only 1 thread become eligible for execution. Then
|
|
||||||
/// that thread would unlock the next and so on. In short, we wait 25 times
|
|
||||||
/// for the thread scheduler to wake up a thread until all users get through.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// So we chose a ManualResetEvent, which will wake up more threads than
|
|
||||||
/// neccessary and possibly cause a period of intense competition for getting
|
|
||||||
/// a lock on the resource, but will make the thread scheduler see all threads
|
|
||||||
/// become eligible for execution.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
#if WINDOWS
|
|
||||||
[Obsolete("Prefer the normal semaphore on Windows builds.")]
|
|
||||||
internal class Semaphore : WaitHandle {
|
|
||||||
#else
|
|
||||||
public class Semaphore : WaitHandle {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>Initializes a new semaphore</summary>
|
|
||||||
public Semaphore() {
|
|
||||||
createEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Initializes a new semaphore</summary>
|
|
||||||
/// <param name="count">
|
|
||||||
/// Number of users that can access the resource at the same time
|
|
||||||
/// </param>
|
|
||||||
public Semaphore(int count) {
|
|
||||||
this.free = count;
|
|
||||||
|
|
||||||
createEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Initializes a new semaphore</summary>
|
|
||||||
/// <param name="initialCount">
|
|
||||||
/// Initial number of users accessing the resource
|
|
||||||
/// </param>
|
|
||||||
/// <param name="maximumCount">
|
|
||||||
/// Maximum numbr of users that can access the resource at the same time
|
|
||||||
/// </param>
|
|
||||||
public Semaphore(int initialCount, int maximumCount) {
|
|
||||||
if(initialCount > maximumCount) {
|
|
||||||
throw new ArgumentOutOfRangeException(
|
|
||||||
"initialCount", "Initial count must not be larger than the maximum count"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.free = maximumCount - initialCount;
|
|
||||||
createEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Immediately releases all resources owned by the instance</summary>
|
|
||||||
/// <param name="explicitDisposing">
|
|
||||||
/// Whether Dispose() has been called explictly
|
|
||||||
/// </param>
|
|
||||||
protected override void Dispose(bool explicitDisposing) {
|
|
||||||
if(this.manualResetEvent != null) {
|
|
||||||
base.SafeWaitHandle = null;
|
|
||||||
|
|
||||||
this.manualResetEvent.Close();
|
|
||||||
this.manualResetEvent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Dispose(explicitDisposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Waits for the resource to become available and locks it
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="millisecondsTimeout">
|
|
||||||
/// Number of milliseconds to wait at most before giving up
|
|
||||||
/// </param>
|
|
||||||
/// <param name="exitContext">
|
|
||||||
/// True to exit the synchronization domain for the context before the wait (if
|
|
||||||
/// in a synchronized context), and reacquire it afterward; otherwise, false.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// True if the resource was available and is now locked, false if
|
|
||||||
/// the timeout has been reached.
|
|
||||||
/// </returns>
|
|
||||||
#if NO_EXITCONTEXT
|
|
||||||
public override bool WaitOne(int millisecondsTimeout) {
|
|
||||||
#else
|
|
||||||
public override bool WaitOne(int millisecondsTimeout, bool exitContext) {
|
|
||||||
#endif
|
|
||||||
for (; ; ) {
|
|
||||||
|
|
||||||
// Lock the resource - even if it is full. We will correct out mistake later
|
|
||||||
// if we overcomitted the resource.
|
|
||||||
int newFree = Interlocked.Decrement(ref this.free);
|
|
||||||
|
|
||||||
// If we got the resource, let the thread pass without further processing.
|
|
||||||
if(newFree >= 0) {
|
|
||||||
if(newFree > 0) {
|
|
||||||
this.manualResetEvent.Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We overcomitted the resource, count it down again. We know that, at least
|
|
||||||
// moments ago, the resource was busy, so block the event.
|
|
||||||
this.manualResetEvent.Reset();
|
|
||||||
Thread.MemoryBarrier();
|
|
||||||
newFree = Interlocked.Increment(ref this.free);
|
|
||||||
|
|
||||||
// Unless we have been preempted by a Release(), we now have to wait for the
|
|
||||||
// resource to become available.
|
|
||||||
if(newFree >= 0) {
|
|
||||||
#if NO_EXITCONTEXT
|
|
||||||
if(!this.manualResetEvent.WaitOne(millisecondsTimeout)) {
|
|
||||||
#else
|
|
||||||
if(!this.manualResetEvent.WaitOne(millisecondsTimeout, exitContext)) {
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // for(; ; )
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Waits for the resource to become available and locks it
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// True if the resource was available and is now locked, false if
|
|
||||||
/// the timeout has been reached.
|
|
||||||
/// </returns>
|
|
||||||
public override bool WaitOne() {
|
|
||||||
#if NO_EXITCONTEXT
|
|
||||||
return WaitOne(-1);
|
|
||||||
#else
|
|
||||||
return WaitOne(-1, false);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Waits for the resource to become available and locks it
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timeout">
|
|
||||||
/// Time span to wait for the lock before giving up
|
|
||||||
/// </param>
|
|
||||||
/// <param name="exitContext">
|
|
||||||
/// True to exit the synchronization domain for the context before the wait (if
|
|
||||||
/// in a synchronized context), and reacquire it afterward; otherwise, false.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// True if the resource was available and is now locked, false if
|
|
||||||
/// the timeout has been reached.
|
|
||||||
/// </returns>
|
|
||||||
#if NO_EXITCONTEXT
|
|
||||||
public override bool WaitOne(TimeSpan timeout) {
|
|
||||||
#else
|
|
||||||
public override bool WaitOne(TimeSpan timeout, bool exitContext) {
|
|
||||||
#endif
|
|
||||||
long totalMilliseconds = (long)timeout.TotalMilliseconds;
|
|
||||||
if((totalMilliseconds < -1) || (totalMilliseconds > int.MaxValue)) {
|
|
||||||
throw new ArgumentOutOfRangeException(
|
|
||||||
"timeout", "Timeout must be either -1 or positive and less than 2^31"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if NO_EXITCONTEXT
|
|
||||||
return WaitOne((int)totalMilliseconds);
|
|
||||||
#else
|
|
||||||
return WaitOne((int)totalMilliseconds, exitContext);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases a lock on the resource. Note that for a reverse counting semaphore,
|
|
||||||
/// it is legal to Release() the resource before locking it.
|
|
||||||
/// </summary>
|
|
||||||
public void Release() {
|
|
||||||
|
|
||||||
// Release one lock on the resource
|
|
||||||
Interlocked.Increment(ref this.free);
|
|
||||||
|
|
||||||
// Wake up any threads waiting for the resource to become available
|
|
||||||
this.manualResetEvent.Set();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Creates the event used to make threads wait for the resource</summary>
|
|
||||||
private void createEvent() {
|
|
||||||
this.manualResetEvent = new ManualResetEvent(false);
|
|
||||||
base.SafeWaitHandle = this.manualResetEvent.SafeWaitHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Event used to make threads wait if the semaphore is full</summary>
|
|
||||||
private ManualResetEvent manualResetEvent;
|
|
||||||
/// <summary>Number of users currently accessing the resource</summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Since this is a reverse counting semaphore, it will be negative if
|
|
||||||
/// the resource is available and 0 if the semaphore is full.
|
|
||||||
/// </remarks>
|
|
||||||
private int free;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Nuclex.Support
|
|
|
@ -332,14 +332,8 @@ namespace Nuclex.Support {
|
||||||
/// <param name="builder">String builder the number will be appended to</param>
|
/// <param name="builder">String builder the number will be appended to</param>
|
||||||
/// <param name="remaining">Remaining digits that will be recursively processed</param>
|
/// <param name="remaining">Remaining digits that will be recursively processed</param>
|
||||||
private static void recursiveAppend(StringBuilder builder, int remaining) {
|
private static void recursiveAppend(StringBuilder builder, int remaining) {
|
||||||
#if !(XBOX360 || WINDOWS_PHONE)
|
|
||||||
int digit;
|
int digit;
|
||||||
int tenth = Math.DivRem(remaining, 10, out digit);
|
int tenth = Math.DivRem(remaining, 10, out digit);
|
||||||
#else
|
|
||||||
int digit = remaining % 10;
|
|
||||||
int tenth = remaining / 10;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(tenth > 0) {
|
if(tenth > 0) {
|
||||||
recursiveAppend(builder, tenth);
|
recursiveAppend(builder, tenth);
|
||||||
}
|
}
|
||||||
|
@ -351,14 +345,8 @@ namespace Nuclex.Support {
|
||||||
/// <param name="builder">String builder the number will be appended to</param>
|
/// <param name="builder">String builder the number will be appended to</param>
|
||||||
/// <param name="remaining">Remaining digits that will be recursively processed</param>
|
/// <param name="remaining">Remaining digits that will be recursively processed</param>
|
||||||
private static void recursiveAppend(StringBuilder builder, long remaining) {
|
private static void recursiveAppend(StringBuilder builder, long remaining) {
|
||||||
#if !(XBOX360 || WINDOWS_PHONE)
|
|
||||||
long digit;
|
long digit;
|
||||||
long tenth = Math.DivRem(remaining, 10, out digit);
|
long tenth = Math.DivRem(remaining, 10, out digit);
|
||||||
#else
|
|
||||||
long digit = remaining % 10;
|
|
||||||
long tenth = remaining / 10;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(tenth > 0) {
|
if(tenth > 0) {
|
||||||
recursiveAppend(builder, tenth);
|
recursiveAppend(builder, tenth);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,65 +58,6 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
#endregion // class MemberInfoComparer
|
#endregion // class MemberInfoComparer
|
||||||
|
|
||||||
#if WINRT
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns all the fields of a type, including those defined in the type's base classes
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">Type whose fields will be returned</param>
|
|
||||||
/// <param name="bindingFlags">Binding flags to use when querying the fields</param>
|
|
||||||
/// <returns>All of the type's fields, including its base types</returns>
|
|
||||||
public static FieldInfo[] GetFieldInfosIncludingBaseClasses(this Type type) {
|
|
||||||
var fieldInfoSet = new HashSet<FieldInfo>(fieldInfos, FieldInfoComparer.Default);
|
|
||||||
|
|
||||||
while(type != typeof(object)) {
|
|
||||||
TypeInfo typeInfo = type.GetTypeInfo();
|
|
||||||
|
|
||||||
foreach(FieldInfo fieldInfo in typeInfo.DeclaredFields) {
|
|
||||||
fieldInfoSet.Add(fieldInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
type = typeInfo.BaseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldInfo[] fieldInfos = new FieldInfo[fieldInfoSet.Count];
|
|
||||||
fieldInfoSet.CopyTo(fieldInfos, 0);
|
|
||||||
return fieldInfos;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif !(XBOX360 || WINDOWS_PHONE)
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns all the fields of a type, including those defined in the type's base classes
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">Type whose fields will be returned</param>
|
|
||||||
/// <param name="bindingFlags">Binding flags to use when querying the fields</param>
|
|
||||||
/// <returns>All of the type's fields, including its base types</returns>
|
|
||||||
public static FieldInfo[] GetFieldInfosIncludingBaseClasses(
|
|
||||||
this Type type, BindingFlags bindingFlags
|
|
||||||
) {
|
|
||||||
FieldInfo[] fieldInfos = type.GetFields(bindingFlags);
|
|
||||||
|
|
||||||
// If this class doesn't have a base, don't waste any time
|
|
||||||
if(type.BaseType != typeof(object)) {
|
|
||||||
var fieldInfoSet = new HashSet<FieldInfo>(fieldInfos, FieldInfoComparer.Default);
|
|
||||||
while(type.BaseType != typeof(object)) {
|
|
||||||
type = type.BaseType;
|
|
||||||
fieldInfos = type.GetFields(bindingFlags);
|
|
||||||
for(int index = 0; index < fieldInfos.Length; ++index) {
|
|
||||||
fieldInfoSet.Add(fieldInfos[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldInfos = new FieldInfo[fieldInfoSet.Count];
|
|
||||||
fieldInfoSet.CopyTo(fieldInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fieldInfos;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // !(XBOX360 || WINDOWS_PHONE)
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all the fields of a type, including those defined in the type's base classes
|
/// Returns all the fields of a type, including those defined in the type's base classes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -164,25 +105,6 @@ namespace Nuclex.Support {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !(XBOX360 || WINDOWS_PHONE)
|
|
||||||
|
|
||||||
#if WINRT
|
|
||||||
|
|
||||||
/// <summary>Determines whether the given type has a default constructor</summary>
|
|
||||||
/// <param name="type">Type which is to be checked</param>
|
|
||||||
/// <returns>True if the type has a default constructor</returns>
|
|
||||||
public static bool HasDefaultConstructor(this Type type) {
|
|
||||||
foreach(ConstructorInfo constructorInfo in type.GetTypeInfo().DeclaredConstructors) {
|
|
||||||
if(constructorInfo.IsPublic && (constructorInfo.GetParameters().Length == 0)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/// <summary>Determines whether the given type has a default constructor</summary>
|
/// <summary>Determines whether the given type has a default constructor</summary>
|
||||||
/// <param name="type">Type which is to be checked</param>
|
/// <param name="type">Type which is to be checked</param>
|
||||||
/// <returns>True if the type has a default constructor</returns>
|
/// <returns>True if the type has a default constructor</returns>
|
||||||
|
@ -199,8 +121,6 @@ namespace Nuclex.Support {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>Determines whether the type has the specified attribute</summary>
|
/// <summary>Determines whether the type has the specified attribute</summary>
|
||||||
/// <typeparam name="TAttribute">Attribute the type will be checked for</typeparam>
|
/// <typeparam name="TAttribute">Attribute the type will be checked for</typeparam>
|
||||||
/// <param name="type">
|
/// <param name="type">
|
||||||
|
@ -211,20 +131,6 @@ namespace Nuclex.Support {
|
||||||
return type.HasAttribute(typeof(TAttribute));
|
return type.HasAttribute(typeof(TAttribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WINRT
|
|
||||||
|
|
||||||
/// <summary>Determines whether the type has the specified attribute</summary>
|
|
||||||
/// <param name="type">
|
|
||||||
/// Type that will be checked for presence of the specified attribute
|
|
||||||
/// </param>
|
|
||||||
/// <param name="attributeType">Attribute the type will be checked for</typeparam>
|
|
||||||
/// <returns>True if the type has the specified attribute, otherwise false</returns>
|
|
||||||
public static bool HasAttribute(this Type type, Type attributeType) {
|
|
||||||
return (type.GetTypeInfo().GetCustomAttribute(attributeType) != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/// <summary>Determines whether the type has the specified attribute</summary>
|
/// <summary>Determines whether the type has the specified attribute</summary>
|
||||||
/// <param name="type">
|
/// <param name="type">
|
||||||
/// Type that will be checked for presence of the specified attribute
|
/// Type that will be checked for presence of the specified attribute
|
||||||
|
@ -236,8 +142,6 @@ namespace Nuclex.Support {
|
||||||
return (attributes != null) && (attributes.Length > 0);
|
return (attributes != null) && (attributes.Length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Nuclex.Support
|
} // namespace Nuclex.Support
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
#region CPL License
|
|
||||||
/*
|
|
||||||
Nuclex Framework
|
|
||||||
Copyright (C) 2002-2014 Nuclex Development Labs
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the IBM Common Public License as
|
|
||||||
published by the IBM Corporation; either version 1.0 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
IBM Common Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the IBM Common Public
|
|
||||||
License along with this library
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Nuclex.Support {
|
|
||||||
|
|
||||||
#if WINDOWS_PHONE
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type-safe weak reference, referencing an object while still allowing
|
|
||||||
/// that object to be garbage collected.
|
|
||||||
/// </summary>
|
|
||||||
public class WeakReference<ReferencedType>
|
|
||||||
where ReferencedType : class {
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the WeakReference class, referencing
|
|
||||||
/// the specified object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="target">The object to track or null.</param>
|
|
||||||
public WeakReference(ReferencedType target) {
|
|
||||||
this.weakReference = new WeakReference(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the WeakReference class, referencing
|
|
||||||
/// the specified object optionally using resurrection tracking.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="target">An object to track.</param>
|
|
||||||
/// <param name="trackResurrection">
|
|
||||||
/// Indicates when to stop tracking the object. If true, the object is tracked
|
|
||||||
/// after finalization; if false, the object is only tracked until finalization.
|
|
||||||
/// </param>
|
|
||||||
public WeakReference(ReferencedType target, bool trackResurrection) {
|
|
||||||
this.weakReference = new WeakReference(target, trackResurrection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implicitly converts a typed WeakReference into a non-typesafe WeakReference
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="self">The types WeakReference that will be converted</param>
|
|
||||||
/// <returns>The non-typesafe WeakReference</returns>
|
|
||||||
public static implicit operator WeakReference(WeakReference<ReferencedType> self) {
|
|
||||||
return self.weakReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the object (the target) referenced by the current WeakReference
|
|
||||||
/// object.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Is null if the object referenced by the current System.WeakReference object
|
|
||||||
/// has been garbage collected; otherwise, a reference to the object referenced
|
|
||||||
/// by the current System.WeakReference object.
|
|
||||||
/// </remarks>
|
|
||||||
/// <exception cref="System.InvalidOperationException">
|
|
||||||
/// The reference to the target object is invalid. This can occur if the current
|
|
||||||
/// System.WeakReference object has been finalized
|
|
||||||
/// </exception>
|
|
||||||
public ReferencedType Target {
|
|
||||||
get { return this.weakReference.Target as ReferencedType; }
|
|
||||||
set { this.weakReference.Target = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// whether the object referenced by the WeakReference has been garbage collected
|
|
||||||
/// </summary>
|
|
||||||
public virtual bool IsAlive {
|
|
||||||
get { return this.weakReference.IsAlive; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the object referenced by the WeakReference is tracked after it is finalized
|
|
||||||
/// </summary>
|
|
||||||
public virtual bool TrackResurrection {
|
|
||||||
get { return this.weakReference.TrackResurrection; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>The non-typesafe WeakReference being wrapped</summary>
|
|
||||||
private WeakReference weakReference;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // WINDOWS_PHONE
|
|
||||||
|
|
||||||
} // namespace Nuclex.Support
|
|
||||||
|
|
|
@ -24,8 +24,6 @@ using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace Nuclex.Support {
|
namespace Nuclex.Support {
|
||||||
|
|
||||||
#if !WINDOWS_PHONE
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type-safe weak reference, referencing an object while still allowing
|
/// Type-safe weak reference, referencing an object while still allowing
|
||||||
/// that object to be garbage collected.
|
/// that object to be garbage collected.
|
||||||
|
@ -98,6 +96,4 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WINDOWS_PHONE
|
|
||||||
|
|
||||||
} // namespace Nuclex.Support
|
} // namespace Nuclex.Support
|
||||||
|
|
Loading…
Reference in New Issue
Block a user