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

📄 contextbase.cpp

📁 C语言库函数的原型,有用的拿去
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    /// <summary>
    ///     When schedulers are nested on the same thread, the nested scheduler creates a new external context that overrides
    ///     the previous context. PopContextFromTls will restore the previous context by setting the TLS value appropriately.
    /// </summary>
    ContextBase* ContextBase::PopContextFromTls()
    {
        ContextBase* pPreviousContext = m_pParentContext;
        TlsSetValue(SchedulerBase::t_dwContextIndex, pPreviousContext);
        m_pParentContext = NULL;
        return pPreviousContext;
    }

    /// <summary>
    ///     When schedulers are nested on the same thread, the nested scheduler creates a new external context that overrides
    ///     the previous context. PushContextToTls will store the previous context and set the new context into TLS.
    /// </summary>
    void ContextBase::PushContextToTls(ContextBase* pParentContext)
    {
        m_pParentContext = pParentContext;

        // For the first context on a thread, we expect the TLS values to be null. If there is a parent context,
        // the TLS value should have been cleared right before nesting.
        ASSERT(TlsGetValue(SchedulerBase::t_dwContextIndex) == NULL);
        TlsSetValue(SchedulerBase::t_dwContextIndex, this);
    }

    /// <summary>
    ///     Context TLS is cleared during nesting on internal contexts before the external context TLS is correctly setup. If not,
    ///     code that executes between the clear and setting the new TLS could get confused.
    /// </summary>
    void ContextBase::ClearContextTls()
    {
        ASSERT(TlsGetValue(SchedulerBase::t_dwContextIndex) != NULL);
        TlsSetValue(SchedulerBase::t_dwContextIndex, NULL);
    }

    /// <summary>
    ///     Returns the scheduler the specified context is associated with.
    /// </summary>
    SchedulerBase* ContextBase::GetScheduler() const
    {
        return m_pScheduler;
    }

    /// <summary>
    ///     Returns the schedule group the specified context is associated with.
    /// </summary>
    ScheduleGroupBase* ContextBase::GetScheduleGroup() const
    {
        return m_pGroup;
    }

    /// <summary>
    ///     Gets the indirect alias.
    /// </summary>
    Concurrency::details::_TaskCollection *ContextBase::GetIndirectAlias() const
    {
        return m_pIndirectAlias;
    }

    /// <summary>
    ///     Sets the indirect alias.
    /// </summary>
    void ContextBase::SetIndirectAlias(_TaskCollection *pAlias)
    {
        m_pIndirectAlias = pAlias;
    }

    /// <summary>
    ///     Sweeps the alias table removing anything that's marked for delete.  This is done every time we create a new direct alias
    ///     in order to avoid growing the table arbitrarily for a context which isn't going away.  Note -- passing a task collection between
    ///     threads is expensive the first time it's used.
    /// </summary>
    void ContextBase::SweepAliasTable()
    {
        int x;
        Hash<_TaskCollection*, _TaskCollection*>::ListNode *pNode = m_aliasTable.First(&x);
        while (pNode != NULL)
        {
            Hash<_TaskCollection*, _TaskCollection*>::ListNode *pNextNode = m_aliasTable.Next(&x, pNode);

            if (pNode->m_value->_IsStaleAlias())
            {
                _TaskCollection *pCollection = pNode->m_value;
                m_aliasTable.Delete(pCollection->_OriginalCollection()); // may delete pNode
                delete pCollection;
            }

            pNode = pNextNode;
        }
    }

    /// <summary>
    ///     Clears the alias table.
    /// </summary>
    void ContextBase::ClearAliasTable()
    {
        int x;
        Hash<_TaskCollection*, _TaskCollection*>::ListNode *pNode = m_aliasTable.First(&x);
        while (pNode != NULL)
        {
            pNode->m_value->_ReleaseAlias();
            pNode = m_aliasTable.Next(&x, pNode);
        }
        m_aliasTable.Wipe();
    }

    /// <summary>
    ///     Called in order to indicate that a collection executing on this context was canceled.  This will often cause cancellation
    ///     and unwinding of the entire context (up to the point where we get to the canceled collection.
    /// </summary>
    void ContextBase::CancelCollection(int inliningDepth)
    {
        InterlockedIncrement(&m_canceledCount);

        long curDepth = m_minCancellationDepth;

        //
        // Keep track of the minimum cancellation depth.
        //
        for(;;)
        {
            if (curDepth != -1 && inliningDepth > curDepth)
                break;

            long xchgDepth = InterlockedCompareExchange(&m_minCancellationDepth, inliningDepth, curDepth);
            if (xchgDepth == curDepth)
                break;

            curDepth = xchgDepth;
        }
    }

    /// <summary>
    ///     When a cancellation bubbles up to the collection being canceled, this function is called in order to stop propagation of
    ///     the cancellation further up the work tree.
    /// </summary>
    bool ContextBase::CollectionCancelComplete(int inliningDepth)
    {
        ASSERT(m_canceledCount > 0);

        //
        // Keep track of minimum cancellation depth.
        //
        InterlockedCompareExchange(&m_minCancellationDepth, -1, inliningDepth);

        return (InterlockedDecrement(&m_canceledCount) == 0);
    }

    /// <summary>
    ///     Send a context ETW event.
    /// </summary>
    void ContextBase::ThrowContextEvent(ConcRT_EventType eventType, UCHAR level, DWORD schedulerId, DWORD contextId)
    {
        if (g_pEtw != NULL)
        {
            CONCRT_TRACE_EVENT_HEADER_COMMON concrtHeader = {0};

            concrtHeader.header.Size = sizeof concrtHeader;
            concrtHeader.header.Flags = WNODE_FLAG_TRACED_GUID;
            concrtHeader.header.Class.Type = (UCHAR)eventType;
            concrtHeader.header.Class.Level = level;
            concrtHeader.header.Guid = ContextEventGuid;

            concrtHeader.SchedulerID = schedulerId;
            concrtHeader.ContextID = contextId;

            g_pEtw->Trace(g_ConcRTSessionHandle, &concrtHeader.header);
        }
    }

    /// <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>
    int ContextBase::EnterCriticalRegion() 
    {
        if (m_pScheduler->IsUMSScheduler())
        {
            return EnterCriticalRegionHelper();
        }

        return 0;
    }

    /// <summary>
    ///     Exits a critical region of the scheduler.
    /// </summary>
    int ContextBase::ExitCriticalRegion() 
    {
        if (m_pScheduler->IsUMSScheduler())
        {
            return ExitCriticalRegionHelper();
        }

        return 0;
    }

    /// <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>
    int ContextBase::EnterHyperCriticalRegion() 
    {
        if (m_pScheduler->IsUMSScheduler())
        {
            return EnterHyperCriticalRegionHelper();
        }

        return 0;
    }

    /// <summary>
    ///     Exits a hyper-critical region of the scheduler.
    /// </summary>
    int ContextBase::ExitHyperCriticalRegion() 
    {
        if (m_pScheduler->IsUMSScheduler())
        {
            return ExitHyperCriticalRegionHelper();
        }

        return 0;
    }

    /// <summary>
    ///    Static version of EnterCriticalRegion. 
    /// </summary>
    void ContextBase::StaticEnterCriticalRegion()
    {
        ContextBase *pContext = SchedulerBase::FastCurrentContext();
        if (pContext != NULL)
            pContext->EnterCriticalRegion();
    }

    /// <summary>
    ///    Static version of EnterHyperCriticalRegion.
    /// </summary>
    void ContextBase::StaticEnterHyperCriticalRegion()
    {
        ContextBase *pContext = SchedulerBase::FastCurrentContext();
        if (pContext != NULL)
            pContext->EnterHyperCriticalRegion();
    }

    /// <summary>
    ///    Static version of ExitCriticalRegion.
    /// </summary>
    void ContextBase::StaticExitCriticalRegion()
    {
        ContextBase *pContext = SchedulerBase::FastCurrentContext();
        if (pContext != NULL)
            pContext->ExitCriticalRegion();
    }

    /// <summary>
    ///    Static version of ExitHyperCriticalRegion.
    /// </summary>
    void ContextBase::StaticExitHyperCriticalRegion()
    {
        ContextBase *pContext = SchedulerBase::FastCurrentContext();
        if (pContext != NULL)
            pContext->ExitHyperCriticalRegion();
    }

    /// <summary>
    ///     Static version of GetCriticalRegionType.
    /// </summary>
    CriticalRegionType ContextBase::StaticGetCriticalRegionType()
    {
        ContextBase *pContext = SchedulerBase::FastCurrentContext();
        if (pContext != NULL)
            return pContext->GetCriticalRegionType();
        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).
    /// </summary>
    bool ContextBase::IsInsideCriticalRegion() const
    {
        if (m_pScheduler->IsUMSScheduler())
            return (GetCriticalRegionType() != OutsideCriticalRegion);
        return true;
    }

} // namespace details
} // namespace Concurrency

⌨️ 快捷键说明

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