Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Threading / ThreadPool.cs / 4 / ThreadPool.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*==============================================================================
**
** Class: ThreadPool
**
**
** Purpose: Class for creating and managing a threadpool
**
**
=============================================================================*/
/*
* Below you'll notice two sets of APIs that are separated by the
* use of 'Unsafe' in their names. The unsafe versions are called
* that because they do not propagate the calling stack onto the
* worker thread. This allows code to lose the calling stack and
* thereby elevate its security privileges. Note that this operation
* is much akin to the combined ability to control security policy
* and control security evidence. With these privileges, a person
* can gain the right to load assemblies that are fully trusted which
* then assert full trust and can call any code they want regardless
* of the previous stack information.
*/
namespace System.Threading {
using System.Security;
using System.Threading;
using System.Runtime.Remoting;
using System.Security.Permissions;
using System;
using Microsoft.Win32;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
internal static class ThreadPoolGlobals
{
//Per-appDomain quantum (in ms) for which the thread keeps processing
//requests in the current domain.
public static uint tpQuantum = 2;
public static int tpWarmupCount = GetProcessorCount() * 2;
public static bool tpHosted = ThreadPool.IsThreadPoolHosted();
public static bool vmTpInitialized;
public static ThreadPoolRequestQueue tpQueue = new ThreadPoolRequestQueue();
[EnvironmentPermissionAttribute(SecurityAction.Assert, Read="NUMBER_OF_PROCESSORS")]
private static int GetProcessorCount()
{
return Environment.ProcessorCount;
}
}
internal sealed class ThreadPoolRequestQueue
{
private _ThreadPoolWaitCallback tpHead;
private _ThreadPoolWaitCallback tpTail;
//The dummy object used to synchronize thread pool queue access.
private Object tpSync;
//The number of work-items in thread pool queue.
private uint tpCount;
public ThreadPoolRequestQueue()
{
tpSync = new Object();
}
public uint EnQueue(_ThreadPoolWaitCallback tpcallBack)
{
uint count = 0;
bool tookLock = false;
bool setNativeTpEvent = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(tpSync);
tookLock = true;
}
catch(Exception)
{
}
if (tookLock)
{
if(tpCount == 0)
{
//Indicate to the VM that there is work in this domain.
//Its important to synchronize this notice, otherwise
//the VM may not schedule any thread in this domain.
setNativeTpEvent = ThreadPool.SetAppDomainRequestActive();
}
tpCount++;
count = tpCount;
if(tpHead == null)
{
tpHead = tpcallBack;
tpTail = tpcallBack;
}
else
{
tpTail._next = tpcallBack;
tpTail = tpcallBack;
}
Monitor.Exit(tpSync);
if(setNativeTpEvent)
{
ThreadPool.SetNativeTpEvent();
}
}
}
return count;
}
public _ThreadPoolWaitCallback DeQueue()
{
bool tookLock = false;
_ThreadPoolWaitCallback tpWaitCallBack = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
Monitor.Enter(tpSync);
tookLock = true;
}
catch(Exception)
{
}
if (tookLock)
{
_ThreadPoolWaitCallback head = tpHead;
if ( head != null)
{
tpWaitCallBack = head;
tpHead = head._next;
tpCount--;
if(tpCount == 0)
{
BCLDebug.Assert(tpHead == null,"TP Queue head expected to be null");
tpTail = null;
//Indicate to the VM that there is no work in this
//domain. Its important to synchronize this notice,
//otherwise the VM may keep calling the Managed
//callbacks endlessly.
ThreadPool.ClearAppDomainRequestActive();
}
}
Monitor.Exit(tpSync);
}
}
return tpWaitCallBack;
}
public uint GetQueueCount()
{
return tpCount;
}
}
internal sealed class RegisteredWaitHandleSafe : CriticalFinalizerObject
{
private static readonly IntPtr InvalidHandle = Win32Native.INVALID_HANDLE_VALUE;
private IntPtr registeredWaitHandle;
private WaitHandle m_internalWaitObject;
private bool bReleaseNeeded = false;
private int m_lock = 0;
internal RegisteredWaitHandleSafe()
{
registeredWaitHandle = InvalidHandle;
}
internal IntPtr GetHandle()
{
return registeredWaitHandle;
}
internal void SetHandle(IntPtr handle)
{
registeredWaitHandle = handle;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal void SetWaitObject(WaitHandle waitObject)
{
// needed for DangerousAddRef
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
m_internalWaitObject = waitObject;
if (waitObject != null)
{
m_internalWaitObject.SafeWaitHandle.DangerousAddRef(ref bReleaseNeeded);
}
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal bool Unregister(
WaitHandle waitObject // object to be notified when all callbacks to delegates have completed
)
{
bool result = false;
// needed for DangerousRelease
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
// lock(this) cannot be used reliably in Cer since thin lock could be
// promoted to syncblock and that is not a guaranteed operation
bool bLockTaken = false;
do
{
if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0)
{
bLockTaken = true;
try
{
if (ValidHandle())
{
result = UnregisterWaitNative(GetHandle(), waitObject == null ? null : waitObject.SafeWaitHandle);
if (result == true)
{
if (bReleaseNeeded)
{
m_internalWaitObject.SafeWaitHandle.DangerousRelease();
bReleaseNeeded = false;
}
// if result not true don't release/suppress here so finalizer can make another attempt
SetHandle(InvalidHandle);
m_internalWaitObject = null;
GC.SuppressFinalize(this);
}
}
}
finally
{
m_lock = 0;
}
}
Thread.SpinWait(1); // yield to processor
}
while (!bLockTaken);
}
return result;
}
private bool ValidHandle()
{
return (registeredWaitHandle != InvalidHandle && registeredWaitHandle != IntPtr.Zero);
}
~RegisteredWaitHandleSafe()
{
// if the app has already unregistered the wait, there is nothing to cleanup
// we can detect this by checking the handle. Normally, there is no race here
// so no need to protect reading of handle. However, if this object gets
// resurrected and then someone does an unregister, it would introduce a race
// PrepareConstrainedRegions call not needed since finalizer already in Cer
// lock(this) cannot be used reliably even in Cer since thin lock could be
// promoted to syncblock and that is not a guaranteed operation
bool bLockTaken = false;
do
{
if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0)
{
bLockTaken = true;
try
{
if (ValidHandle())
{
WaitHandleCleanupNative(registeredWaitHandle);
if (bReleaseNeeded)
{
m_internalWaitObject.SafeWaitHandle.DangerousRelease();
bReleaseNeeded = false;
}
SetHandle(InvalidHandle);
m_internalWaitObject = null;
}
}
finally
{
m_lock = 0;
}
}
Thread.SpinWait(1); // yield to processor
}
while (!bLockTaken);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void WaitHandleCleanupNative(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool UnregisterWaitNative(IntPtr handle, SafeHandle waitObject);
}
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class RegisteredWaitHandle : MarshalByRefObject
{
private RegisteredWaitHandleSafe internalRegisteredWait;
internal RegisteredWaitHandle()
{
internalRegisteredWait = new RegisteredWaitHandleSafe();
}
internal void SetHandle(IntPtr handle)
{
internalRegisteredWait.SetHandle(handle);
}
internal void SetWaitObject(WaitHandle waitObject)
{
internalRegisteredWait.SetWaitObject(waitObject);
}
[System.Runtime.InteropServices.ComVisible(true)]
// This is the only public method on this class
public bool Unregister(
WaitHandle waitObject // object to be notified when all callbacks to delegates have completed
)
{
return internalRegisteredWait.Unregister(waitObject);
}
}
[System.Runtime.InteropServices.ComVisible(true)]
public delegate void WaitCallback(Object state);
[System.Runtime.InteropServices.ComVisible(true)]
public delegate void WaitOrTimerCallback(Object state, bool timedOut); // signalled or timed out
internal class _ThreadPoolWaitCallback
{
WaitCallback _waitCallback;
ExecutionContext _executionContext;
Object _state;
//ThreadPoolWaitCallBack is the unit of thread pool work, and is
//chained together. The _next field is the link. This field should be
//accessible to the Thread pool queue in order to reduce number of
//object allocations as this is on a perf-critical path.
protected internal _ThreadPoolWaitCallback _next;
static internal ContextCallback _ccb = new ContextCallback(WaitCallback_Context);
static internal void WaitCallback_Context(Object state)
{
_ThreadPoolWaitCallback obj = (_ThreadPoolWaitCallback)state;
obj._waitCallback(obj._state);
}
internal _ThreadPoolWaitCallback(WaitCallback waitCallback, Object state, bool compressStack, ref StackCrawlMark stackMark)
{
_waitCallback = waitCallback;
_state = state;
if (compressStack && !ExecutionContext.IsFlowSuppressed())
{
// clone the exection context
_executionContext = ExecutionContext.Capture(ref stackMark);
ExecutionContext.ClearSyncContext(_executionContext);
}
}
// call back helper
// This function dispatches requests to the user-callbacks. The
// work-items are fetched from the per-appdomain queue in a loop until
// either there is no more work or the quantum has expired. The quantum
// is enforced to maintain fairness among appdomains.
static internal void PerformWaitCallback(Object state)
{
int totTime=0;
_ThreadPoolWaitCallback tpWaitCallBack = null;
int startTime = Environment.TickCount;
do
{
tpWaitCallBack = ThreadPoolGlobals.tpQueue.DeQueue();
if ( tpWaitCallBack == null)
{
break;
}
// This call in the VM updates queue counts, number of
// completed requests, etc. More importantly, it also
// resets thread state like CriticalRegionCount, priority etc.
//
ThreadPool.CompleteThreadPoolRequest(ThreadPoolGlobals.tpQueue.GetQueueCount());
PerformWaitCallbackInternal(tpWaitCallBack);
int endTime = Environment.TickCount;
totTime = (endTime - startTime);
// Check to see if quantum has expired.
if(totTime > ThreadPoolGlobals.tpQuantum)
{
if(ThreadPool.ShouldReturnToVm())
{
break;
}
}
} while (true);
}
static internal void PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
{
// call directly if it is an unsafe call OR EC flow is suppressed
if (tpWaitCallBack._executionContext == null)
{
WaitCallback callback = tpWaitCallBack._waitCallback;
callback(tpWaitCallBack._state);
}
else
{
ExecutionContext.Run(tpWaitCallBack._executionContext, _ccb, tpWaitCallBack);
}
}
};
internal class _ThreadPoolWaitOrTimerCallback
{
WaitOrTimerCallback _waitOrTimerCallback;
ExecutionContext _executionContext;
Object _state;
static private ContextCallback _ccbt = new ContextCallback(WaitOrTimerCallback_Context_t);
static private ContextCallback _ccbf = new ContextCallback(WaitOrTimerCallback_Context_f);
internal _ThreadPoolWaitOrTimerCallback(WaitOrTimerCallback waitOrTimerCallback, Object state, bool compressStack, ref StackCrawlMark stackMark)
{
_waitOrTimerCallback = waitOrTimerCallback;
_state = state;
if (compressStack && !ExecutionContext.IsFlowSuppressed())
{
// capture the exection context
_executionContext = ExecutionContext.Capture(ref stackMark);
ExecutionContext.ClearSyncContext(_executionContext);
}
}
static private void WaitOrTimerCallback_Context_t(Object state)
{
WaitOrTimerCallback_Context(state, true);
}
static private void WaitOrTimerCallback_Context_f(Object state)
{
WaitOrTimerCallback_Context(state, false);
}
static private void WaitOrTimerCallback_Context(Object state, bool timedOut)
{
_ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state;
helper._waitOrTimerCallback(helper._state, timedOut);
}
// call back helper
static internal void PerformWaitOrTimerCallback(Object state, bool timedOut)
{
_ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state;
BCLDebug.Assert(helper != null, "Null state passed to PerformWaitOrTimerCallback!");
// call directly if it is an unsafe call OR EC flow is suppressed
if (helper._executionContext == null)
{
WaitOrTimerCallback callback = helper._waitOrTimerCallback;
callback(helper._state, timedOut);
}
else
{
if (timedOut)
ExecutionContext.Run(helper._executionContext.CreateCopy(), _ccbt, helper);
else
ExecutionContext.Run(helper._executionContext.CreateCopy(), _ccbf, helper);
}
}
};
[CLSCompliant(false)]
[System.Runtime.InteropServices.ComVisible(true)]
unsafe public delegate void IOCompletionCallback(uint errorCode, // Error code
uint numBytes, // No. of bytes transferred
NativeOverlapped* pOVERLAP // ptr to OVERLAP structure
);
[HostProtection(Synchronization=true, ExternalThreading=true)]
public static class ThreadPool
{
[SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
public static bool SetMaxThreads(int workerThreads, int completionPortThreads)
{
return SetMaxThreadsNative(workerThreads, completionPortThreads);
}
public static void GetMaxThreads(out int workerThreads, out int completionPortThreads)
{
GetMaxThreadsNative(out workerThreads, out completionPortThreads);
}
[SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
public static bool SetMinThreads(int workerThreads, int completionPortThreads)
{
return SetMinThreadsNative(workerThreads, completionPortThreads);
}
public static void GetMinThreads(out int workerThreads, out int completionPortThreads)
{
GetMinThreadsNative(out workerThreads, out completionPortThreads);
}
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads)
{
GetAvailableThreadsNative(out workerThreads, out completionPortThreads);
}
[CLSCompliant(false)]
public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
uint millisecondsTimeOutInterval,
bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
}
[CLSCompliant(false),
SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
uint millisecondsTimeOutInterval,
bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
}
private static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
uint millisecondsTimeOutInterval,
bool executeOnlyOnce, // NOTE: we do not allow other options that allow the callback to be queued as an APC
ref StackCrawlMark stackMark,
bool compressStack
)
{
if (RemotingServices.IsTransparentProxy(waitObject))
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy"));
RegisteredWaitHandle registeredWaitHandle = new RegisteredWaitHandle();
if (callBack != null)
{
_ThreadPoolWaitOrTimerCallback callBackHelper = new _ThreadPoolWaitOrTimerCallback(callBack, state, compressStack, ref stackMark);
state = (Object)callBackHelper;
// call SetWaitObject before native call so that waitObject won't be closed before threadpoolmgr registration
// this could occur if callback were to fire before SetWaitObject does its addref
registeredWaitHandle.SetWaitObject(waitObject);
IntPtr nativeRegisteredWaitHandle = RegisterWaitForSingleObjectNative(waitObject,
state,
millisecondsTimeOutInterval,
executeOnlyOnce,
registeredWaitHandle,
ref stackMark,
compressStack);
registeredWaitHandle.SetHandle(nativeRegisteredWaitHandle);
}
else
{
throw new ArgumentNullException("WaitOrTimerCallback");
}
return registeredWaitHandle;
}
public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
int millisecondsTimeOutInterval,
bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
)
{
if (millisecondsTimeOutInterval < -1)
throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
}
[SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
int millisecondsTimeOutInterval,
bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
)
{
if (millisecondsTimeOutInterval < -1)
throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
}
public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
long millisecondsTimeOutInterval,
bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
)
{
if (millisecondsTimeOutInterval < -1)
throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
}
[SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
long millisecondsTimeOutInterval,
bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
)
{
if (millisecondsTimeOutInterval < -1)
throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
}
public static RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
TimeSpan timeout,
bool executeOnlyOnce
)
{
long tm = (long)timeout.TotalMilliseconds;
if (tm < -1)
throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
if (tm > (long) Int32.MaxValue)
throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,true);
}
[SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
Object state,
TimeSpan timeout,
bool executeOnlyOnce
)
{
long tm = (long)timeout.TotalMilliseconds;
if (tm < -1)
throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
if (tm > (long) Int32.MaxValue)
throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,false);
}
public static bool QueueUserWorkItem(
WaitCallback callBack, // NOTE: we do not expose options that allow the callback to be queued as an APC
Object state
)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return QueueUserWorkItemHelper(callBack,state,ref stackMark,true);
}
public static bool QueueUserWorkItem(
WaitCallback callBack // NOTE: we do not expose options that allow the callback to be queued as an APC
)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return QueueUserWorkItemHelper(callBack,null,ref stackMark,true);
}
[SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
public static bool UnsafeQueueUserWorkItem(
WaitCallback callBack, // NOTE: we do not expose options that allow the callback to be queued as an APC
Object state
)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return QueueUserWorkItemHelper(callBack,state,ref stackMark,false);
}
//ThreadPool has per-appdomain managed queue of work-items. The VM is
//responsible for just scheduling threads into appdomains. After that
//work-items are dispatched from the managed queue.
private static bool QueueUserWorkItemHelper(WaitCallback callBack, Object state, ref StackCrawlMark stackMark, bool compressStack )
{
bool success = true;
if (callBack != null)
{
//The thread pool maintains a per-appdomain managed work queue.
//New thread pool entries are added in the managed queue.
//The VM is responsible for the actual growing/shrinking of
//threads.
_ThreadPoolWaitCallback tpcallBack = new _ThreadPoolWaitCallback(callBack, state, compressStack, ref stackMark);
if(!ThreadPoolGlobals.vmTpInitialized)
{
ThreadPool.InitializeVMTp();
ThreadPoolGlobals.vmTpInitialized = true;
}
uint queueCount;
queueCount = ThreadPoolGlobals.tpQueue.EnQueue(tpcallBack);
//Make sure the unmanaged thread pool creates some threads
//before accepting requests in the managed queue.
if( (ThreadPoolGlobals.tpHosted) || (queueCount < ThreadPoolGlobals.tpWarmupCount))
{
success = AdjustThreadsInPool(ThreadPoolGlobals.tpQueue.GetQueueCount());
}
else
{
UpdateNativeTpCount(ThreadPoolGlobals.tpQueue.GetQueueCount());
}
return success;
}
else
{
throw new ArgumentNullException("WaitCallback");
}
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool AdjustThreadsInPool(uint QueueLength);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void UpdateNativeTpCount(uint QueueLength);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe private static extern bool PostQueuedCompletionStatus(NativeOverlapped* overlapped);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void InitializeVMTp();
[CLSCompliant(false)]
[SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
unsafe public static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped)
{
return PostQueuedCompletionStatus(overlapped);
}
// Native methods:
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool SetMinThreadsNative(int workerThreads, int completionPortThreads);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool SetMaxThreadsNative(int workerThreads, int completionPortThreads);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void GetMinThreadsNative(out int workerThreads, out int completionPortThreads);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void GetMaxThreadsNative(out int workerThreads, out int completionPortThreads);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void GetAvailableThreadsNative(out int workerThreads, out int completionPortThreads);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void CompleteThreadPoolRequest(uint QueueLength);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool ShouldReturnToVm();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool SetAppDomainRequestActive();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern void ClearAppDomainRequestActive();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool IsThreadPoolHosted();
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void SetNativeTpEvent();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern IntPtr RegisterWaitForSingleObjectNative(
WaitHandle waitHandle,
Object state,
uint timeOutInterval,
bool executeOnlyOnce,
RegisteredWaitHandle registeredWaitHandle,
ref StackCrawlMark stackMark,
bool compressStack
);
[Obsolete("ThreadPool.BindHandle(IntPtr) has been deprecated. Please use ThreadPool.BindHandle(SafeHandle) instead.", false)]
[SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static bool BindHandle(
IntPtr osHandle
)
{
return BindIOCompletionCallbackNative(osHandle);
}
[SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static bool BindHandle(SafeHandle osHandle)
{
if (osHandle == null)
throw new ArgumentNullException("osHandle");
bool ret = false;
bool mustReleaseSafeHandle = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
osHandle.DangerousAddRef(ref mustReleaseSafeHandle);
ret = BindIOCompletionCallbackNative(osHandle.DangerousGetHandle());
}
finally {
if (mustReleaseSafeHandle)
osHandle.DangerousRelease();
}
return ret;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private static extern bool BindIOCompletionCallbackNative(IntPtr fileHandle);
}
}
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- OperatingSystem.cs
- InsufficientMemoryException.cs
- DataTemplateKey.cs
- CompiledRegexRunnerFactory.cs
- WindowShowOrOpenTracker.cs
- SqlNode.cs
- SineEase.cs
- PenCursorManager.cs
- WindowsRegion.cs
- RelationshipSet.cs
- EntityDesignerBuildProvider.cs
- WmpBitmapDecoder.cs
- TakeQueryOptionExpression.cs
- WindowsTab.cs
- ResourceReader.cs
- Relationship.cs
- CanonicalFormWriter.cs
- AttachedPropertyBrowsableForTypeAttribute.cs
- OrderByQueryOptionExpression.cs
- RadioButtonRenderer.cs
- DSASignatureFormatter.cs
- XmlDocumentType.cs
- MissingSatelliteAssemblyException.cs
- Enum.cs
- TaskFormBase.cs
- AssemblyEvidenceFactory.cs
- TypeConverterHelper.cs
- TreeNode.cs
- TypeToTreeConverter.cs
- StructuralCache.cs
- DoubleAnimationBase.cs
- AppDomainUnloadedException.cs
- SchemaImporterExtensionElement.cs
- ContainerParagraph.cs
- DataBinding.cs
- XmlBinaryReader.cs
- SymbolResolver.cs
- AssemblySettingAttributes.cs
- Behavior.cs
- ReflectionUtil.cs
- XmlDataSource.cs
- OleCmdHelper.cs
- MediaElement.cs
- UnknownWrapper.cs
- Registry.cs
- XsdCachingReader.cs
- TextChangedEventArgs.cs
- PackagePartCollection.cs
- Hash.cs
- StatusBarAutomationPeer.cs
- ScrollBar.cs
- ResXFileRef.cs
- CodeObject.cs
- SettingsContext.cs
- HtmlGenericControl.cs
- DataGridPageChangedEventArgs.cs
- PersonalizationProviderHelper.cs
- Preprocessor.cs
- HttpApplicationStateBase.cs
- activationcontext.cs
- XmlWriter.cs
- FocusManager.cs
- OleDbTransaction.cs
- MultiTouchSystemGestureLogic.cs
- SchemaAttDef.cs
- ContainerFilterService.cs
- NotFiniteNumberException.cs
- BindingMemberInfo.cs
- ScriptServiceAttribute.cs
- TextCharacters.cs
- TableParaClient.cs
- LazyInitializer.cs
- ObjectListComponentEditor.cs
- ObjectDataSourceMethodEventArgs.cs
- EntityDataSourceWizardForm.cs
- ObjectSelectorEditor.cs
- Group.cs
- FileDialogCustomPlace.cs
- ReadOnlyDictionary.cs
- ActionItem.cs
- UInt16.cs
- UdpConstants.cs
- CallbackValidatorAttribute.cs
- XmlElement.cs
- SubMenuStyleCollection.cs
- StringAnimationBase.cs
- PointCollection.cs
- BasicHttpBinding.cs
- ResourcePart.cs
- TreeNodeStyle.cs
- XmlSchemaComplexContent.cs
- CodeGotoStatement.cs
- MetabaseServerConfig.cs
- XmlUtil.cs
- XmlNamespaceMapping.cs
- ToolBarTray.cs
- InheritanceContextChangedEventManager.cs
- DockPattern.cs
- WindowsFont.cs
- ExpandSegment.cs