// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// UMSBackgroundPoller.cpp
//
// A background thread responsible for polling for contexts which had a failed ExecuteUmsThread and inject them on our
// abstraction of a completion list.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#include "concrtinternal.h"
namespace Concurrency
{
namespace details
{
///
/// Constructs a new UMS background poller.
///
///
/// How often (in milliseconds) the background thread should poll for awakenings.
///
UMSBackgroundPoller::UMSBackgroundPoller() :
m_hNotification(NULL),
m_pollCount(0)
{
m_hNotification = CreateEventW(NULL, FALSE, FALSE, NULL);
if (m_hNotification == NULL)
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
}
///
/// Destructs a UMS background poller.
///
UMSBackgroundPoller::~UMSBackgroundPoller()
{
CloseHandle(m_hNotification);
}
///
/// Causes the background poller thread to poll for waking of pThreadProxy and insert it into the completion
/// list of pSchedulerProxy.
///
///
/// The thread proxy to poll for awakening of.
///
///
/// The scheduler proxy to insert pThreadProxy into the completion list of when awake.
///
void UMSBackgroundPoller::InsertProxyInCompletionWhenAwake(UMSThreadProxy *pThreadProxy, UMSSchedulerProxy *pSchedulerProxy)
{
pThreadProxy->m_pPollInsertionProxy = pSchedulerProxy;
#if defined(_DEBUG)
pThreadProxy->m_backgroundPollerEntry.m_pollStart = _ReadTimeStampCounter();
pThreadProxy->m_backgroundPollerEntry.m_pollCount = 0;
#endif // _DEBUG
m_pollProxies.AddTail(&(pThreadProxy->m_backgroundPollerEntry.m_link));
if (InterlockedIncrement(&m_pollCount) == 1)
{
SetEvent(m_hNotification);
}
}
///
/// Wakes up and polls periodically the list of proxies that are required and inserts them into the appropriate transfer
/// lists if they are awake.
///
bool UMSBackgroundPoller::DoPolling()
{
SafeRWList::_Scoped_lock writeLock(m_pollProxies);
ListEntry *pEntry = m_pollProxies.First();
while (pEntry != NULL)
{
ListEntry *pNext = m_pollProxies.Next(pEntry);
UMSBackgroundPollerEntry *pPollerEntry = CONTAINING_RECORD(pEntry, UMSBackgroundPollerEntry, m_link);
UMSThreadProxy *pProxy = CONTAINING_RECORD(pPollerEntry, UMSThreadProxy, m_backgroundPollerEntry);
if (!pProxy->IsSuspended())
{
m_pollProxies.UnlockedRemove(pEntry);
InterlockedDecrement(&m_pollCount);
pProxy->m_pPollInsertionProxy->PushPolledCompletion(pProxy);
}
#if defined(_DEBUG)
else
{
pPollerEntry->m_pollCount++;
}
#endif // defined(_DEBUG)
pEntry = pNext;
}
return (m_pollCount == 0);
}
} // namespace details
} // namespace Concurrency