The AffineThreadPool class now also tries to create CPU-affine threads on the full .NET framework (which uses P/Invoke and tries to lock a managed thread to a system thread, probably needs some work for Mono)
git-svn-id: file:///srv/devel/repo-conversion/nusu@174 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
05e4aebaac
commit
e74955b161
|
@ -22,6 +22,7 @@ using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Nuclex.Support {
|
namespace Nuclex.Support {
|
||||||
|
|
||||||
|
@ -94,7 +95,12 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
// We can only use these hardware thread indices on the XBox 360
|
// We can only use these hardware thread indices on the XBox 360
|
||||||
#if XBOX360
|
#if XBOX360
|
||||||
XboxHardwareThreads = new Queue<int>(new int[] { 5, 4, 3, 1 });
|
hardwareThreads = new Queue<int>(new int[] { 5, 4, 3, 1 });
|
||||||
|
#else
|
||||||
|
hardwareThreads = new Queue<int>(CpuCores);
|
||||||
|
for(int core = CpuCores; core >= 1; --core) {
|
||||||
|
hardwareThreads.Enqueue(core);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create all of the worker threads
|
// Create all of the worker threads
|
||||||
|
@ -194,16 +200,28 @@ namespace Nuclex.Support {
|
||||||
|
|
||||||
/// <summary>A thread worker function that processes items from the work queue</summary>
|
/// <summary>A thread worker function that processes items from the work queue</summary>
|
||||||
private static void ProcessQueuedItems() {
|
private static void ProcessQueuedItems() {
|
||||||
|
|
||||||
|
int hardwareThreadIndex;
|
||||||
|
lock(hardwareThreads) {
|
||||||
|
hardwareThreadIndex = hardwareThreads.Dequeue();
|
||||||
|
}
|
||||||
|
|
||||||
#if XBOX360
|
#if XBOX360
|
||||||
// MSDN states that SetProcessorAffinity() should be called from the thread
|
// MSDN states that SetProcessorAffinity() should be called from the thread
|
||||||
// whose affinity is being changed.
|
// whose affinity is being changed.
|
||||||
int hardwareThreadIndex;
|
|
||||||
lock(XboxHardwareThreads) {
|
|
||||||
hardwareThreadIndex = XboxHardwareThreads.Dequeue();
|
|
||||||
}
|
|
||||||
Thread.CurrentThread.SetProcessorAffinity(new int[] { hardwareThreadIndex });
|
Thread.CurrentThread.SetProcessorAffinity(new int[] { hardwareThreadIndex });
|
||||||
|
#else
|
||||||
|
// Prevent this managed thread from impersonating another system thread.
|
||||||
|
// Threads in .NET can take
|
||||||
|
Thread.BeginThreadAffinity();
|
||||||
|
|
||||||
|
ProcessThread thread = getCurrentProcessThread();
|
||||||
|
if(thread != null) {
|
||||||
|
thread.IdealProcessor = hardwareThreadIndex;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Keep processing tasks indefinitely
|
// Keep processing tasks indefinitely
|
||||||
for(; ; ) {
|
for(; ; ) {
|
||||||
UserWorkItem workItem = getNextWorkItem();
|
UserWorkItem workItem = getNextWorkItem();
|
||||||
|
@ -228,6 +246,21 @@ namespace Nuclex.Support {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Retrieves the ProcessThread for the calling thread</summary>
|
||||||
|
/// <returns>The ProcessThread for the calling thread</returns>
|
||||||
|
private static ProcessThread getCurrentProcessThread() {
|
||||||
|
int threadId = GetCurrentThreadId();
|
||||||
|
|
||||||
|
ProcessThreadCollection threads = Process.GetCurrentProcess().Threads;
|
||||||
|
for(int index = 0; index < threads.Count; ++index) {
|
||||||
|
if(threads[index].Id == threadId) {
|
||||||
|
return threads[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Obtains the next work item from the queue</summary>
|
/// <summary>Obtains the next work item from the queue</summary>
|
||||||
/// <returns>The next work item in the queue</returns>
|
/// <returns>The next work item in the queue</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
@ -270,10 +303,13 @@ 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 AssertionDelegate AssertionHandler = DefaultAssertionHandler;
|
public static AssertionDelegate AssertionHandler = DefaultAssertionHandler;
|
||||||
|
|
||||||
#if XBOX360
|
/// <summary>Retrieves the calling thread's thread id</summary>
|
||||||
/// <summary>XNA games on the XBox 360 can use only 4 of 6 hardware threads</summary>
|
/// <returns>The thread is of the calling thread</returns>
|
||||||
private static Queue<int> XboxHardwareThreads;
|
[DllImport("kernel32.dll")]
|
||||||
#endif
|
private static extern int GetCurrentThreadId();
|
||||||
|
|
||||||
|
/// <summary>Available hardware threads the thread pool threads pick from</summary>
|
||||||
|
private static Queue<int> hardwareThreads;
|
||||||
/// <summary>Queue of all the callbacks waiting to be executed.</summary>
|
/// <summary>Queue of all the callbacks waiting to be executed.</summary>
|
||||||
private static Queue<UserWorkItem> userWorkItems;
|
private static Queue<UserWorkItem> userWorkItems;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user