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:
parent
11610cbbbe
commit
66f0ae9b34
|
@ -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")]
|
||||||
|
|
|
@ -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>();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user