📄 threadproxyfactory.h
字号:
if (pProxy->GetStackSize() == s_proxyStackSize[i])
{
// If the pool is close to full, cancel the proxy and allow the thread to exit.
if (m_proxyPool[i].Count() < s_bucketSize)
{
m_proxyPool[i].Push(pProxy);
// After adding the thread proxy to the pool, check if the factory has been shut down.
// At shutdown, the flag is set to true before the shutdown routine goes through
// and retires all the thread proxies. However, if we've added this proxy after
// that point, there is a good chance that the shutdown routine missed us. We
// need to make sure the bucket is empty and all proxies are retired, in this case.
if (m_fShutdown)
{
pProxy = m_proxyPool[i].Flush();
while (pProxy != NULL)
{
FreeThreadProxy *pNextProxy = LockFreeStack<FreeThreadProxy>::Next(pProxy);
// Retiring the proxy will cause it to perform any necessary cleanup, and exit its dispatch loop.
Retire(pProxy);
pProxy = pNextProxy;
}
}
pProxy = NULL;
}
break;
}
}
}
if (pProxy != NULL)
{
Retire(pProxy);
}
}
/// <summary>
/// Initiates shutdown of the factory, and deletes it if shutdown can be completed inline.
/// </summary>
virtual void ShutdownFactory()
{
m_fShutdown = true;
RetireThreadProxies();
Release();
}
private:
/// <summary>
/// Creates a new thread proxy.
/// </summary>
virtual FreeThreadProxy* Create(unsigned int stackSize)
{
return new FreeThreadProxy(this, stackSize);
}
/// <summary>
/// Retires a thread proxy.
/// </summary>
virtual void Retire(FreeThreadProxy *pProxy)
{
// Canceling the proxy will cause it to perform any necessary cleanup, and exit its dispatch loop.
pProxy->Cancel();
}
// Reference count for the thread proxy factory. For details, see comments in the constructor of ThreadProxy.
volatile LONG m_referenceCount;
// Flag that is set to true if shutdown has been initiated on the thread proxy factory.
volatile bool m_fShutdown;
};
/// <summary>
/// A factory that creates UMS thread proxies for UMS thread schedulers.
/// </summary>
class UMSFreeThreadProxyFactory : public ThreadProxyFactory<UMSFreeThreadProxy, UMSFreeThreadProxyFactory>
{
public:
/// <summary>
/// Creates a new UMS thread proxy factory.
/// </summary>
UMSFreeThreadProxyFactory(ThreadProxyFactoryManager * pManager) :
ThreadProxyFactory(pManager),
m_pCompletionList(NULL),
m_hCompletionEvent(NULL)
{
if (!UMS::CreateUmsCompletionList(&m_pCompletionList))
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
if (!UMS::GetUmsCompletionListEvent(m_pCompletionList, &m_hCompletionEvent))
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
m_pUmsThreadEngine = new TransmogrifiedPrimary();
}
/// <summary>
/// Destroys a UMS thread proxy factory.
/// </summary>
virtual ~UMSFreeThreadProxyFactory()
{
}
/// <summary>
/// Initiates shutdown of the factory, and deletes it if shutdown can be completed inline.
/// </summary>
virtual void ShutdownFactory()
{
RetireThreadProxies();
m_pUmsThreadEngine->Shutdown();
if (m_pCompletionList != NULL)
UMS::DeleteUmsCompletionList(m_pCompletionList);
// A UMS thread proxy factory can be deleted inline. This is because it is guaranteed that all thread proxies
// that were loaned out to UMS scheduler proxies were added back to the idle pool before it is possible for
// the factory to be shutdown. (The factory is shutdown by the RM only after all scheduler proxies have shutdown).
delete this;
}
/// <summary>
/// UMS thread proxy factories do not support reference counting.
/// </summary>
LONG Reference()
{
return 0;
}
/// <summary>
/// UMS thread proxy factories do not support reference counting.
/// </summary>
LONG Release()
{
return 0;
}
private:
/// <summary>
/// Creates a new thread proxy.
/// </summary>
virtual UMSFreeThreadProxy * Create(unsigned int stackSize)
{
HANDLE hObjects[2];
UMSFreeThreadProxy *pProxy = new UMSFreeThreadProxy(this, m_pCompletionList, stackSize);
hObjects[0] = pProxy->m_hBlock;
hObjects[1] = m_hCompletionEvent;
//
// Make *ABSOLUTELY CERTAIN* that the thread has come back on a completion list prior to returning from Create. This will ensure that a primary
// can execute it right away (which is the likely use for creating one of these to begin with).
//
for(;;)
{
DWORD result = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
if (result == WAIT_OBJECT_0)
{
return pProxy;
}
PUMS_CONTEXT pUMSContext;
if (!UMS::DequeueUmsCompletionListItems(m_pCompletionList, 0, &pUMSContext))
{
delete pProxy;
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
}
while (pUMSContext != NULL)
{
UMSFreeThreadProxy* pReturnedProxy = static_cast<UMSFreeThreadProxy*>(UMSFreeThreadProxy::FromUMSContext(pUMSContext));
RPMTRACE(MTRACE_EVT_ORIGINALCOMPLETION, pReturnedProxy, NULL, pUMSContext);
pUMSContext = UMS::GetNextUmsListItem(pUMSContext);
// Let the thread engine run it to ThreadMain
m_pUmsThreadEngine->QueueToCompletion(pReturnedProxy);
}
}
}
/// <summary>
/// Prepares a thread proxy for use.
/// </summary>
/// <param name="pProxy">
/// The proxy to prepare.
/// </param>
/// <param name="contextPriority">
/// The required thread priority for the thread proxy.
/// <param>
virtual void Prepare(UMSFreeThreadProxy *pProxy, int contextPriority)
{
ThreadProxyFactory::Prepare(pProxy, contextPriority);
pProxy->ClearCriticalRegion();
}
/// <summary>
/// Retires a thread proxy.
/// </summary>
virtual void Retire(UMSFreeThreadProxy *pProxy)
{
RPMTRACE(MTRACE_EVT_RETIRE, pProxy, NULL, NULL);
// Canceling the proxy will cause it to perform any necessary cleanup, and exit its dispatch loop.
pProxy->Cancel();
m_pUmsThreadEngine->QueueToCompletion(pProxy);
}
// The primary responsible for retiring UTs.
TransmogrifiedPrimary *m_pUmsThreadEngine;
// The initial completion list upon which threads created from this factory will be placed. No UMS thread can be scheduled by any primary
// until it appears on an initial UMS completion list. We will block Create until this is done.
PUMS_COMPLETION_LIST m_pCompletionList;
// The UMS completion list event.
HANDLE m_hCompletionEvent;
};
//
// A class that holds a collection of thread proxy factories, one for each type of thread proxy.
//
class ThreadProxyFactoryManager
{
public:
/// <summary>
/// Creates a thread proxy factory manager.
/// </summary>
ThreadProxyFactoryManager();
/// <summary>
/// Destroys a thread proxy factory manager.
/// </summary>
~ThreadProxyFactoryManager();
/// <summary>
/// Returns a Win32 thread proxy factory.
/// </summary>
FreeThreadProxyFactory * GetFreeThreadProxyFactory();
/// <summary>
/// Returns a UMS thread proxy factory.
/// </summary>
UMSFreeThreadProxyFactory * GetUMSFreeThreadProxyFactory();
/// <summary>
/// Returns the TLS index used to store execution resource information by subscribed threads and thread proxies.
/// </summary>
DWORD GetExecutionResourceTls() const
{
return m_dwExecutionResourceTlsIndex;
}
private:
// A thread proxy factory for Win32 thread proxies.
FreeThreadProxyFactory * m_pFreeThreadProxyFactory;
// A thread proxy factory for UMS thread proxies.
UMSFreeThreadProxyFactory * m_pUMSFreeThreadProxyFactory;
// An index to a TLS slot where execution resource pointers are stored.
DWORD m_dwExecutionResourceTlsIndex;
// A lock that guards creation of the thread proxy factories.
_NonReentrantBlockingLock m_proxyFactoryCreationLock;
};
} // namespace details
} // namespace Concurrency
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -