📄 contextbase.h
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// Context.h
//
// Header file containing the metaphor for an execution context/stack/thread.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#pragma once
// Defines used for context blocking (m_blockedState):
// * Possible blocked states
#define CONTEXT_NOT_BLOCKED 0x0
#define CONTEXT_BLOCKED 0x1
#define CONTEXT_UMS_SYNC_BLOCKED 0x2
#define CONTEXT_UMS_ASYNC_BLOCKED 0x4
// * Useful bit-masks
#define CONTEXT_SYNC_BLOCKED (CONTEXT_BLOCKED | CONTEXT_UMS_SYNC_BLOCKED)
#define CONTEXT_UMS_BLOCKED (CONTEXT_UMS_SYNC_BLOCKED | CONTEXT_UMS_ASYNC_BLOCKED)
namespace Concurrency
{
namespace details
{
/// <summary>
/// Implements the base class for a ConcRT execution context.
/// </summary>
class ContextBase : public Context
{
public:
//
// Public Methods
//
/// <summary>
/// Constructor
/// </summary>
ContextBase(SchedulerBase *pScheduler, bool fIsExternal);
/// <summary>
/// Returns a unique identifier to the context.
/// </summary>
virtual unsigned int GetId() const;
/// <summary>
/// Returns an identifier to the virtual processor the context is currently executing on, if any.
/// </summary>
virtual unsigned int GetVirtualProcessorId() const =0;
/// <summary>
/// Returns an identifier to the schedule group the context is currently working on, if any.
/// <summary>
virtual unsigned int GetScheduleGroupId() const;
/// <summary>
/// Returns the reference count of the underlying schedule group, which is equivalent
/// to the number of contexts performing work on the schedule group.
/// <summary>
unsigned int ScheduleGroupRefCount() const;
/// <summary>
/// Causes the context to block, yielding the virtual processor to another context.
/// </summary>
virtual void Block() =0;
/// <summary>
/// Unblocks the context and makes it runnable.
/// </summary>
virtual void Unblock() =0;
/// <summary>
/// Determines whether or not the context is synchronously blocked at this given time.
/// </summary>
/// <returns>
/// Whether context is in synchronous block state.
/// </returns>
virtual bool IsSynchronouslyBlocked() const =0;
/// <summary>
/// Returns whether the context is blocked or not. Note that this definition of blocked is "blocked and requires
/// eventual reexecution -- e.g.: finalization will call this during the sweep phase).
/// </summary>
bool IsBlocked() const
{
return (m_blockedState != CONTEXT_NOT_BLOCKED);
}
/// <summary>
/// Yields execution to a different runnable context, and puts this context on a runnables collection.
/// If no context is found to yield to, the context continues to run.
/// </summary>
virtual void Yield() =0;
/// <summary>
/// Yields execution to a different runnable context, and puts this context on a runnables collection.
/// If no context is found to yield to, the context continues to run.
///
/// This is intended for spin loops.
/// </summary>
virtual void SpinYield() =0;
/// <summary>
/// See comments for Concurrency::Context::Oversubscribe.
/// </summary>
virtual void Oversubscribe(bool beginOversubscription) =0;
/// <summary>
/// Cleans up the Context.
/// </summary>
void Cleanup();
/// <summary>
/// Allocates a block of memory of the size specified.
/// </summary>
/// <param name="numBytes">
/// Number of bytes to allocate.
/// </param>
/// <returns>
/// A pointer to newly allocated memory.
/// </returns>
virtual void* Alloc(size_t numBytes) =0;
/// <summary>
/// Frees a block of memory previously allocated by the Alloc API.
/// </summary>
/// <param name="pAllocation">
/// A pointer to an allocation previously allocated by Alloc.
/// </param>
virtual void Free(void* pAllocation) =0;
/// <summary>
/// Enters a critical region of the scheduler. Calling this guarantees that the virtual processor on which this context lives
/// is guaranteed to be stable throughout the critical region. For some context types, this is virtually a NOP. For others
/// (UMS), this makes it appear that blocking on the context actually blocks the UMS thread instead of triggering return to
/// primary. Note that critical regions suppress asynchronous blocking but not synchronous blocking.
/// </summary>
virtual int EnterCriticalRegionHelper()
{
CORE_ASSERT(Context::CurrentContext() == this);
return ++m_criticalRegionCount;
}
int EnterCriticalRegion();
/// <summary>
/// Static version of EnterCriticalRegion.
/// </summary>
static void StaticEnterCriticalRegion();
/// <summary>
/// Enters a hyper-critical region of the scheduler. Calling this guarantees not only the conditions of a critical region but it
/// guarantees that synchronous blocking is suppressed as well. This allows for lock sharing between the primary and hyper-critical
/// regions running on UTs. No lock sharing can occur between the inside of this region type and the outside of this region type
/// on a UT.
/// </summary>
virtual int EnterHyperCriticalRegionHelper()
{
m_criticalRegionCount++;
return ++m_hyperCriticalRegionCount;
}
int EnterHyperCriticalRegion();
/// <summary>
/// Static version of EnterHyperCriticalRegion.
/// </summary>
static void StaticEnterHyperCriticalRegion();
/// <summary>
/// Exits a critical region of the scheduler.
/// </summary>
virtual int ExitCriticalRegionHelper()
{
CORE_ASSERT(m_criticalRegionCount > 0);
CORE_ASSERT(Context::CurrentContext() == this);
return --m_criticalRegionCount;
}
int ExitCriticalRegion();
/// <summary>
/// Static version of ExitCriticalRegion.
/// </summary>
static void StaticExitCriticalRegion();
/// <summary>
/// Exits a hyper-critical region of the scheduler.
/// </summary>
virtual int ExitHyperCriticalRegionHelper()
{
CORE_ASSERT(m_hyperCriticalRegionCount > 0);
CORE_ASSERT(m_criticalRegionCount > 0);
m_criticalRegionCount--;
return --m_hyperCriticalRegionCount;
}
int ExitHyperCriticalRegion();
/// <summary>
/// Static version of ExitHyperCriticalRegion.
/// </summary>
static void StaticExitHyperCriticalRegion();
/// <summary>
/// Checks if a context is in a critical region. This is only safe from either the current context or from a UMS primary which
/// has woken due to a given context blocking.
/// </summary>
virtual CriticalRegionType GetCriticalRegionType() const
{
if (m_hyperCriticalRegionCount > 0)
return InsideHyperCriticalRegion;
if (m_criticalRegionCount > 0)
return InsideCriticalRegion;
return OutsideCriticalRegion;
}
/// <summary>
/// Since critical region counts are turned off for thread schedulers, this method is used
/// where the return value is expected to be true. For a thread scheduler, it always returns true.
/// For a ums scheduler it returns (GetCriticalRegionType() != OutsideCriticalRegion).
/// IsInsideContextLevelCriticalRegion only checks (ContextBase::GetCriticalRegionType() != OutsideCriticalRegion).
/// </summary>
bool IsInsideCriticalRegion() const;
/// <summary>
/// Static version of GetCriticalRegionType.
/// </summary>
static CriticalRegionType StaticGetCriticalRegionType();
/// <summary>
/// Set critical region counts to zero
/// </summary>
void ClearCriticalRegion()
{
m_hyperCriticalRegionCount = m_criticalRegionCount = 0;
}
#if defined(_DEBUG)
/// <summary>
/// Tells the context it's shutting down a virtual processor and normal lock validations don't apply.
/// </summary>
void SetShutdownValidations()
{
m_fShutdownValidations = true;
}
/// <summary>
/// Re-enable normal lock validations
/// </summary>
void ClearShutdownValidations()
{
m_fShutdownValidations = false;
}
/// <summary>
/// Returns whether or not the context is in a "shutting down a virtual processor" mode where normal lock validations don't apply.
/// </summary>
bool IsShutdownValidations() const
{
return m_fShutdownValidations;
}
#endif // _DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -