⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 internalcontextbase.h

📁 C语言库函数的原型,有用的拿去
💻 H
📖 第 1 页 / 共 2 页
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// InternalContextBase.h
//
// Header file containing the base class definition for an internal execution context.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#pragma once

namespace Concurrency
{
namespace details
{

    /// <summary>
    ///     Implements the base class for ConcRT internal contexts.
    /// </summary>

    class InternalContextBase : public IExecutionContext, public ContextBase
    {
    public:

        using ContextBase::GetId;

        //
        // Public methods
        //

        /// <summary>
        ///     Constructs the base class object for an internal context.
        /// </summary>
        InternalContextBase(SchedulerBase *pScheduler);

        /// <summary>
        ///     Causes the internal context to block yielding the virtual processor to a different internal context.
        /// </summary>
        virtual void Block();

        /// <summary>
        ///     Unblocks the internal context putting it on a runnables collection in its schedule group.
        /// </summary>
        virtual void Unblock();

        /// <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
        {
            return (m_contextSwitchingFence == 2);
        }

        /// <summary>
        ///     Yields the virtual processor to a different runnable internal context if one is found.
        /// </summary>
        virtual void Yield();

        /// <summary>
        ///     Yields the virtual processor to a different runnable internal context if one is found.
        ///    
        ///     This is intended for spin loops.
        /// </summary>
        virtual void SpinYield();

        /// <summary>
        ///     See comments for Concurrency::Context::Oversubscribe.
        /// </summary>
        virtual void Oversubscribe(bool beginOversubscription);

        /// <summary>
        ///     Destroys the base class object for an internal context.
        /// </summary>
        virtual ~InternalContextBase();

        /// <summary>
        ///     Returns an identifier to the virtual processor the context is currently executing on, if any.
        /// </summary>
        virtual unsigned int GetVirtualProcessorId() const;

        /// <summary>
        ///     Toggle the flag that ensures that scheduler is not deleted until adding is completely finished.
        /// </summary>
        /// <param name="value">
        ///     The value to set the flag to.
        /// </param>
        void CrossGroupRunnable(LONG value) { m_fCrossGroupRunnable = value; }

        /// <summary>
        ///     Set the value of the oversubscribed virtual processor for a context that invokes Oversubscribe.
        /// </summary>
        void SetOversubscribedVProc(VirtualProcessor * pVirtualProcessor) { m_pOversubscribedVProc = pVirtualProcessor; }

        /// <summary>
        ///     Called to retreive the oversubscribed vproc and reset it to null.
        /// </summary>
        VirtualProcessor * GetAndResetOversubscribedVProc(VirtualProcessor * pExpectedVirtualProcessor);

        /// <summary>
        ///     Returns a scheduler unique identifier for the context.
        /// </summary>
        /// <returns>
        ///     The Id of the context. 
        /// </returns>
        virtual unsigned int GetId() const;

        /// <summary>
        ///     Returns the scheduler to which this context belongs.
        /// </summary>
        /// <returns>
        ///     The owning scheduler.
        /// </returns>
        virtual IScheduler * GetScheduler();

        /// <summary>
        ///     Returns the thread proxy which is executing this context.  Until the Dispatch method has been called on the given
        ///     context, this will return NULL.  Once the Dispatch method has been called, this returns the IThreadProxy which
        ///     was passed into the Dispatch method.
        /// </summary>
        /// <returns>
        ///     The thread proxy which dispatched this particular context, otherwise NULL.
        /// </returns>
        virtual IThreadProxy * GetProxy();

#if _DEBUG
        // _DEBUG helper
        DWORD GetThreadId() const;
#endif

        /// <summary>
        ///     Sets the thread proxy which is executing this context.  The caller must save this and return it upon a call to the GetProxy method.
        ///     Note that the resource manager guarantees stability of the thread proxy while inside the Dispatch method.
        /// </summary>
        /// <param name="pThreadProxy">
        ///     The thread proxy which dispatched this particular context.
        /// </param>
        /// <returns>
        ///     An indication of success.
        /// </returns>
        virtual void SetProxy(IThreadProxy *pThreadProxy);

        /// <summary>
        ///     The method that is called when a thread proxy starts executing a particular context.  The thread proxy which executes
        ///     the context is passed into this method and must be saved and returned on a call to the get_Proxy method.
        /// </summary>
        /// <param name="pDispatchState">
        ///     The state under which this IExecutionContext is being dispatched.
        /// </param>
        virtual void Dispatch(DispatchState * pDispatchState);

        /// <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);

        /// <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);

        /// <summary>
        ///     Swaps the existing schedule group with the one supplied. This function should be called when the context already
        ///     has a schedule group. It decrements the existing group reference count, and references the new one if the caller
        ///     indicates so.
        /// </summary>
        /// <param name="pNewGroup">
        ///     The new group to assign to the context. This may be NULL.
        /// </param>
        /// <param name="referenceNewGroup">
        ///     Whether the context should reference the new group. In some cases there may be an existing reference
        ///     transferred to the context, in which case this parameter is false.
        /// </param>
        void SwapScheduleGroup(ScheduleGroupBase* pNewGroup, bool referenceNewGroup = false);

        /// <summary>
        ///     Increments the count of work coming in.
        /// </summary>
        void IncrementEnqueuedTaskCounter()
        {
            if (m_pScheduler->IsUMSScheduler())
                IncrementEnqueuedTaskCounterHelper();
            else 
                m_pVirtualProcessor->m_enqueuedTaskCounter++;
        }

        void IncrementEnqueuedTaskCounterHelper();

        /// <summary>
        ///     Increments the count of work being done.
        /// </summary>
        void IncrementDequeuedTaskCounter()
        {
            if (m_pScheduler->IsUMSScheduler())
                IncrementDequeuedTaskCounterHelper(1);
            else
                m_pVirtualProcessor->m_dequeuedTaskCounter++;
        }

        /// <summary>
        ///     Increments the count of work being done.
        /// </summary>
        void IncrementDequeuedTaskCounter(unsigned int count)
        {
            if (m_pScheduler->IsUMSScheduler())
                IncrementDequeuedTaskCounterHelper(count);
            else
                m_pVirtualProcessor->m_dequeuedTaskCounter += count;
        }

        void IncrementDequeuedTaskCounterHelper(unsigned int count);

        /// <summary>
        ///     In some cases internal context has not yet recieved a virtual processor so we have
        ///     to save the fact that the work was dequeued and we'll update it in Affinitize.
        /// </summary>
        void SaveDequeuedTask()
        {
            ASSERT(!m_fHasDequeuedTask);
            m_fHasDequeuedTask = true;
        }

        /// <summary>
        ///     Notifies that some work was skipped by an iteration of dispatch loop of this context
        /// </summary>
        void NotifyWorkSkipped() 
        {
            m_fWorkSkipped = true;
        }
        
#if defined(_DEBUG)
        /// <summary>
        ///     Gets the debug bits.
        /// </summary>
        DWORD GetDebugBits() const
        {
            return m_ctxDebugBits;
        }

        /// <summary>
        ///     Sets a series of internal debugging bits for the context.
        /// </summary>
        /// <param name="bits">
        ///     A bitmapped series of CTX_DEBUGBIT_* flags to set within the context.
        /// </param>
        void SetDebugBits(DWORD bits)
        {
            m_ctxDebugBits |= bits;
        }

        /// <summary>
        ///     Clears a series of internal debugging bits for the context.
        /// </summary>
        /// <param name="bits">
        ///     A bitmapped series of CTX_DEBUGBIT_* flags to clear within the context.
        /// </param>
        void ClearDebugBits(DWORD bits)
        {
            m_ctxDebugBits &= ~bits;
        }

        /// <summary>
        ///     Completelky clears all debug bits.
        /// </summary>
        void ClearDebugBits()
        {
            m_ctxDebugBits = 0;
        }

        void NotifyAcquired()
        {
            m_lastAcquiredTid = GetCurrentThreadId();
        }
#endif // _DEBUG

#if _UMSTRACE
        void Trace(int traceEvt, void *pCtx, void *pVproc, ULONG_PTR data)
        {
            m_traceBuffer.Trace(traceEvt, pCtx, pVproc, data);
        }
#endif // _UMSTRACE

        /// <summary>
        ///     Returns whether the context is in the idle pool or not. Finalization will call this during the sweep phase to 
        //      determine all the blocked contexts. A context in the idle pool is considered "not blocked".
        /// </summary>
        bool IsIdle() const
        {
            return m_fIdle;
        }

        /// <summary>
        ///     Prepare a context for execution by associating a scheduler group/chore with it. Scheduler
        //      shall call this routine before executing an internal context
        /// </summary>
        void PrepareForUse(ScheduleGroupBase* pGroup, _Chore *pChore, bool choreStolen);

        /// <summary>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -