The AffineThreadPool class will now work on Mono as well; fixed naming inconsistency for the EnumHelper class; inverted the counting direction used by the Semaphore class so it is easier to read (most other Semaphores count in the direction it is using now)

git-svn-id: file:///srv/devel/repo-conversion/nusu@187 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2010-01-20 20:21:23 +00:00
parent 11610cbbbe
commit 66f0ae9b34
3 changed files with 34 additions and 27 deletions

View File

@ -198,18 +198,20 @@ namespace Nuclex.Support {
// be called from the thread whose affinity is being changed. // be called from the thread whose affinity is being changed.
Thread.CurrentThread.SetProcessorAffinity(new int[] { hardwareThreadIndex }); Thread.CurrentThread.SetProcessorAffinity(new int[] { hardwareThreadIndex });
#else #else
// Prevent this managed thread from impersonating another system thread. if(Environment.OSVersion.Platform == PlatformID.Win32NT) {
// In .NET, managed threads can supposedly be moved to different system threads // Prevent this managed thread from impersonating another system thread.
// and, more worryingly, even fibers. This should make sure we're sitting on // In .NET, managed threads can supposedly be moved to different system threads
// a normal system thread and stay with that thread during our lifetime. // and, more worryingly, even fibers. This should make sure we're sitting on
Thread.BeginThreadAffinity(); // a normal system thread and stay with that thread during our lifetime.
Thread.BeginThreadAffinity();
// Assign the ideal processor, but don't force it. It's not a good idea to // Assign the ideal processor, but don't force it. It's not a good idea to
// circumvent the thread scheduler of a desktop machine, so we try to play nice. // circumvent the thread scheduler of a desktop machine, so we try to play nice.
int threadId = GetCurrentThreadId(); int threadId = GetCurrentThreadId();
ProcessThread thread = GetProcessThread(threadId); ProcessThread thread = GetProcessThread(threadId);
if(thread != null) { if(thread != null) {
thread.IdealProcessor = hardwareThreadIndex; thread.IdealProcessor = hardwareThreadIndex;
}
} }
#endif #endif
@ -280,7 +282,7 @@ namespace Nuclex.Support {
/// <summary>Delegate used to handle assertion checks in the code</summary> /// <summary>Delegate used to handle assertion checks in the code</summary>
public static volatile ExceptionDelegate ExceptionHandler = DefaultExceptionHandler; public static volatile ExceptionDelegate ExceptionHandler = DefaultExceptionHandler;
#if !XBOX360 #if !XBOX360 // Only called if platform is Win32NT
/// <summary>Retrieves the calling thread's thread id</summary> /// <summary>Retrieves the calling thread's thread id</summary>
/// <returns>The thread is of the calling thread</returns> /// <returns>The thread is of the calling thread</returns>
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]

View File

@ -70,14 +70,14 @@ namespace Nuclex.Support {
// Look for the lowest value in the enumeration. We initialize the lowest value // Look for the lowest value in the enumeration. We initialize the lowest value
// to the first enumeration value so we don't have to use some arbitrary starting // to the first enumeration value so we don't have to use some arbitrary starting
// value which might actually appear in the enumeration. // value which might actually appear in the enumeration.
EnumType lowest = values[0]; EnumType lowestValue = values[0];
for(int index = 1; index < values.Length; ++index) { for(int index = 1; index < values.Length; ++index) {
if(values[index].CompareTo(lowest) < 0) { if(values[index].CompareTo(lowestValue) < 0) {
lowest = values[index]; lowestValue = values[index];
} }
} }
return lowest; return lowestValue;
} }
/// <summary>Retrieves a list of all values contained in an enumeration</summary> /// <summary>Retrieves a list of all values contained in an enumeration</summary>
@ -85,6 +85,10 @@ namespace Nuclex.Support {
/// Type of the enumeration whose values will be returned /// Type of the enumeration whose values will be returned
/// </typeparam> /// </typeparam>
/// <returns>All values contained in the specified enumeration</returns> /// <returns>All values contained in the specified enumeration</returns>
/// <remarks>
/// This method produces collectable garbage so it's best to only call it once
/// and cache the result.
/// </remarks>
public static EnumType[] GetValues<EnumType>() { public static EnumType[] GetValues<EnumType>() {
#if XBOX360 #if XBOX360
return GetValuesXbox360<EnumType>(); return GetValuesXbox360<EnumType>();

View File

@ -68,7 +68,7 @@ namespace Nuclex.Support {
/// Number of users that can access the resource at the same time /// Number of users that can access the resource at the same time
/// </param> /// </param>
public Semaphore(int count) { public Semaphore(int count) {
this.users = -count; this.free = count;
createEvent(); createEvent();
} }
@ -87,7 +87,7 @@ namespace Nuclex.Support {
); );
} }
this.users = initialCount - maximumCount; // should be negative! this.free = maximumCount - initialCount;
createEvent(); createEvent();
} }
@ -129,11 +129,11 @@ namespace Nuclex.Support {
// Lock the resource - even if it is full. We will correct out mistake later // Lock the resource - even if it is full. We will correct out mistake later
// if we overcomitted the resource. // if we overcomitted the resource.
int newUsers = Interlocked.Increment(ref this.users); int newFree = Interlocked.Decrement(ref this.free);
// If we got the resource, let the thread pass without further processing. // If we got the resource, let the thread pass without further processing.
if(newUsers <= 0) { if(newFree >= 0) {
if(newUsers < 0) { if(newFree > 0) {
this.manualResetEvent.Set(); this.manualResetEvent.Set();
} }
@ -144,16 +144,17 @@ namespace Nuclex.Support {
// moments ago, the resource was busy, so block the event. // moments ago, the resource was busy, so block the event.
this.manualResetEvent.Reset(); this.manualResetEvent.Reset();
Thread.MemoryBarrier(); Thread.MemoryBarrier();
newUsers = Interlocked.Decrement(ref this.users); newFree = Interlocked.Increment(ref this.free);
// Unless we have been preempted by a Release(), we now have to wait for the // Unless we have been preempted by a Release(), we now have to wait for the
// resource to become available. // resource to become available.
if(newUsers >= 0) { if(newFree >= 0) {
if(!this.manualResetEvent.WaitOne(millisecondsTimeout, exitContext)) { if(!this.manualResetEvent.WaitOne(millisecondsTimeout, exitContext)) {
return false; return false;
} }
} }
}
} // for(; ; )
} }
#if XBOX360 #if XBOX360
@ -198,12 +199,12 @@ namespace Nuclex.Support {
/// <summary> /// <summary>
/// Releases a lock on the resource. Note that for a reverse counting semaphore, /// Releases a lock on the resource. Note that for a reverse counting semaphore,
/// it is legal to Release() the resource before before locking it. /// it is legal to Release() the resource before locking it.
/// </summary> /// </summary>
public void Release() { public void Release() {
// Release one lock on the resource // Release one lock on the resource
int newUsers = Interlocked.Decrement(ref this.users); int newFree = Interlocked.Increment(ref this.free);
// Wake up any threads waiting for the resource to become available // Wake up any threads waiting for the resource to become available
this.manualResetEvent.Set(); this.manualResetEvent.Set();
@ -227,7 +228,7 @@ namespace Nuclex.Support {
/// Since this is a reverse counting semaphore, it will be negative if /// Since this is a reverse counting semaphore, it will be negative if
/// the resource is available and 0 if the semaphore is full. /// the resource is available and 0 if the semaphore is full.
/// </remarks> /// </remarks>
private int users; private int free;
} }