📄 context.cpp
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// Context.cpp
//
// Implementation of static context APIs
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#include "concrtinternal.h"
namespace Concurrency
{
/// <summary>
/// Returns a per scheduler unique identifier for the current context.
/// </summary>
/// <returns>
/// A per scheduler unique identifier for the current context or -1 if no such context exists.
/// </returns>
unsigned int Context::Id()
{
const ContextBase *pContext = SchedulerBase::SafeFastCurrentContext();
return (pContext != NULL ? pContext->GetId() : UINT_MAX);
}
/// <summary>
/// Returns an identifier for the virtual processor the current context is executing on.
/// </summary>
/// <returns>
/// An identifier for the virtual processor the current context is executing on or -1 if there is no such context
/// or it is not executing on a virtual processor at present.
/// </returns>
unsigned int Context::VirtualProcessorId()
{
const ContextBase *pContext = SchedulerBase::SafeFastCurrentContext();
return (pContext != NULL ? pContext->GetVirtualProcessorId() : UINT_MAX);
}
/// <summary>
/// Returns an identifier for the schedule group the current context is working on.
/// </summary>
/// <returns>
/// An identifier for the schedule group the current context is working on or -1 if there is no such context
/// or it is not executing a schedule group at present.
/// </returns>
unsigned int Context::ScheduleGroupId()
{
const ContextBase *pContext = SchedulerBase::SafeFastCurrentContext();
return (pContext != NULL ? pContext->GetScheduleGroupId() : UINT_MAX);
}
/// <summary>
/// Causes the current context to block, yielding execution to another context. If the current
/// thread does not have a ConcRT context associated with it, it is inducted into one.
/// </summary>
void Context::Block()
{
return SchedulerBase::CurrentContext()->Block();
}
/// <summary>
/// Yields execution so that another context may execute. The current context is placed on the
/// scheduler's list of runnable contexts. If the current thread does not have a context, it is inducted
/// into a ConcRT context. If no other function is available to yield to, the function simply returns.
/// </summary>
void Context::Yield()
{
SchedulerBase::CurrentContext()->Yield();
}
/// <summary>
/// Yields execution so that another context may execute. The current context is placed on the
/// scheduler's list of runnable contexts. If the current thread does not have a context, it is inducted
/// into a ConcRT context. If no other function is available to yield to, the function simply returns.
///
/// This is intended for spin loops.
/// </summary>
void Context::_SpinYield()
{
SchedulerBase::CurrentContext()->SpinYield();
}
/// <summary>
/// Returns an indication of whether the task collection which is currently executing inline on the current context
/// is in the midst of an active cancellation (or will be shortly).
/// </summary>
bool Context::IsCurrentTaskCollectionCanceling()
{
ContextBase *pCurrentContext = SchedulerBase::SafeFastCurrentContext();
if (pCurrentContext != NULL)
{
//
// If a structured collection has an unstructured collection as a parent,
// then GetExecutingCollection will always return the parent.
//
_TaskCollectionBase *pCollection = pCurrentContext->GetExecutingCollection();
if (pCollection != NULL)
{
if (pCollection->_IsStructured())
return static_cast<details::_StructuredTaskCollection*>(pCollection)->_IsCanceling();
else
return static_cast<details::_TaskCollection*>(pCollection)->_IsCanceling();
}
}
return false;
}
/// <summary>
/// Returns the ConcRT context associated with the current thread.
/// </summary>
/// <returns>
/// A pointer to the ConcRT context associated with the current thread if it exists. If one does not exist,
/// a new context is created.
/// <returns>
__ecount(1) Context* Context::CurrentContext()
{
return SchedulerBase::CurrentContext();
}
/// <summary>
/// Depending on the argument, causes the scheduler to add an extra virtual processor for the
/// duration of a block of code or remove a previously added one.
///
/// Oversubscribe(true);
/// /* some slow kernel or I/O code, etc.*/
/// Oversubscribe(false);
///
/// An extra virtual processor is allocated on the current hardware thread between the two calls
/// to Oversubscribe. If additional idle virtual processors are available, the virtual processor is created
/// and made available, but if no available virtual processors exist, the virtual processor is kicked into
/// action with an internal context that searches for work.
/// Calls to Oversubscribe(TRUE) must be matched with calls to Oversubscribe(FALSE) -> calls can be nested,
/// but only a maximum of one additional virtual processor is created. The additional vproc, if any, will
/// be retired after the outermost call to Oversubscribe(FALSE), as soon as the currently executing root
/// chore on the vproc is completed.
/// </summary>
/// <param name="beginOversubscription">
/// [in] A boolean value specifying whether oversubscription is to be turned on or off.
/// </param>
void Context::Oversubscribe(bool beginOversubscription)
{
SchedulerBase::CurrentContext()->Oversubscribe(beginOversubscription);
}
} // namespace Concurrency
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -