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

📄 taskcollection.cpp

📁 C语言库函数的原型,有用的拿去
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }

        return !fThrow;
    }

    /// <summary>
    ///     Destructs a new unstructured task collection
    /// </summary>
    _TaskCollection::~_TaskCollection()
    {
        bool fThrow = false;

        //
        // Direct alias destruction should not attempt to go through any wait/abort cycle.  It's simply the deletion/abandonment
        // of the alias.  The original collection might not even be around to touch.
        //
        if (!_IsDirectAlias())
        {
            fThrow = !_TaskCleanup(false);

            //
            // Go through and cleanup direct aliases.  Note that there's an inherent problem and conflict here:
            //
            // - An internal context may go away and need to destroy its alias table -- it cannot touch the original task collection since it does
            //   not know when that collection may be deleted (it may have already)
            //
            // - The original task collection may be deleted but it cannot remove entries from alias tables.
            //
            // In order to resolve this and appropriately free the aliases, there's a simple cleanup state machine with a set of rules to act
            // as a last man out frees the object.
            //
            //     - If the destructor runs, it flags each alias so that the context can delete them
            //     - When a context exits, it flags each alias so that the destructor deletes them
            //     - First one to reach an alias with the flag set frees it.
            //
            // Note this is essentially a fixed reference count of two, but done with a bit flag to allow for other shared state in the flags.
            //
            if (_M_pOriginalCollection == this)
            {
                _TaskCollection *pAlias = _M_pNextAlias;
                _TaskCollection *pNext = NULL;

                for (; pAlias; pAlias = pNext)
                {
                    pNext = pAlias->_M_pNextAlias;
                    pAlias->_ReleaseAlias();
                }
            }
        }

        TaskStack *pStack = reinterpret_cast<TaskStack *> (_M_pTaskExtension);
        if (pStack) delete pStack;

        if (fThrow)
            throw missing_wait();
    }

    /// <summary>
    ///     Constructs a new unstructured task collection as an alias of an already existing one.  An alias in this particular 
    ///     case is a context-local representation of the original task collection. 
    /// </summary>
    /// <param name="pOriginCollection">
    ///     The source of the aliasing.  The newly constructed collection will be a direct or indirect
    ///     alias of this collection
    /// </param>
    /// <param name="fDirectAlias">
    ///     Indicates whether the collection is a direct alias (the collection is used on an arbitrary thread
    ///     not related to stolen work) or an indirect alias (a collection implicitly created for stolen chores).
    /// </param>
    _TaskCollection::_TaskCollection(_TaskCollection *pOriginCollection, bool fDirectAlias) :
        _M_pOriginalCollection(pOriginCollection->_M_pOriginalCollection),
        _M_pTaskExtension(NULL),
        _M_executionStatus(TASKCOLLECTION_EXECUTION_STATUS_CLEAR),
        _M_flags(0),
        _M_stackPos(0)
    {
        //
        // CurrentContext may create a context
        //
        _M_pOwningContext = SchedulerBase::CurrentContext();
        ContextBase *pCurrentContext = reinterpret_cast<ContextBase*> (_M_pOwningContext);
        _M_pParent = pCurrentContext->GetExecutingCollection();
        _Initialize();
        _M_event.set();
        if (fDirectAlias)
        {
            _TaskCollection *pAlias = _M_pOriginalCollection->_M_pNextAlias;
            for (;;)
            {
                _M_pNextAlias = pAlias;
                _TaskCollection *pxchgAlias = reinterpret_cast <_TaskCollection *> (InterlockedCompareExchangePointer((volatile PVOID*)&_M_pOriginalCollection->_M_pNextAlias, this, pAlias));
                if (pxchgAlias == pAlias)
                    break;
                
                pAlias = pxchgAlias;
            }
        }
        else
        {
            _M_flags |= TASKCOLLECTIONFLAG_ALIAS_IS_INDIRECT;
            _M_pNextAlias = NULL;
        }

        _M_boundQueueId = SchedulerBase::FastCurrentContext()->GetWorkQueueIdentity();
        _M_inlineFlags = 0;
    }

    /// <summary>
    ///     Determines whether the alias is stale (waiting to be deleted)
    /// </summary>
    bool _TaskCollection::_IsStaleAlias() const
    {
        ASSERT (_IsAlias());
        return (_M_flags & TASKCOLLECTIONFLAG_ALIAS_FREE_ON_VIEW) != 0;
    }

    /// <summary>
    ///     Releases an alias (frees it if appropriate)
    /// </summary>
    void _TaskCollection::_ReleaseAlias()
    {
        ASSERT (_IsAlias());
        long flags = _M_flags;

        //
        // Future proof against usage of the flags field.
        //
        for (;;)
        {
            //
            // If we observed the flag but weren't the one to set it, we're responsible for freeing the alias.
            //
            if (flags & TASKCOLLECTIONFLAG_ALIAS_FREE_ON_VIEW)
                break;

            long xchgFlags = InterlockedCompareExchange(&_M_flags, flags | TASKCOLLECTIONFLAG_ALIAS_FREE_ON_VIEW, flags);
            if (xchgFlags == flags)
            {
                //
                // If we get here, *this* is poison. 
                //
                return;
            }

            flags = xchgFlags;

        }

        delete this;

    }

    /// <summary>
    ///     Returns the original task collection (the collection that this object is an alias for).
    /// </summary>
    _TaskCollection *_TaskCollection::_OriginalCollection() const
    {
        ASSERT(_IsAlias());
        return _M_pOriginalCollection;
    }

    /// <summary>
    ///     Returns the alias for the specified task collection on the current context.  A NULL return would indicate
    ///     an error condition (e.g.: inability to allocate a new direct alias, etc...).
    /// </summary>
    /// <returns>
    ///     The alias for the specified task collection on the current context or NULL on error
    /// </returns>
    _TaskCollection *_TaskCollection::_Alias()
    {
        ASSERT(!_IsDirectAlias());

        //
        // Someone may have used this task collection on an arbitrary new thread -- hence, we need to make sure there's
        // a current context (not FastCurrentContext).  Note that such usage will imply a direct alias (the code
        // will fall through to that point)
        //
        // Note that a task collection is bound to both the thread and the work queue.  Normally, these won't differ, but may
        // in certain cases where a task collection is used on an internal context which exits before deletion and we get into
        // detached work queue cases.  Those queues get deleted when empty and it's entirely possible that another queue
        // could get reallocated in the exact same memory location.  Hence -- we bind to an identity assigned to each
        // work queue.  Thus, aliasing checks both the owning context and the queue identity.
        //
        ContextBase *pCurrentContext = SchedulerBase::CurrentContext();
        DWORD queueId = pCurrentContext->GetWorkQueueIdentity();
        if (pCurrentContext != reinterpret_cast<ContextBase *> (_M_pOwningContext) || queueId != _M_boundQueueId)
        {
            //
            // The task collection has been used on an alternate thread.  We need an alias for the task collection.  The alias can
            // take one of two forms: a direct alias (the collection is used on an arbitrary thread) or an indirect alias
            // (the collection is used during a stolen chore).
            //
            // Indirect aliases are simple: they have the lifetime (and wait span) of the stolen chore.  Direct aliases
            // have far more complication.
            //
            _TaskCollection *pIndirectAlias = pCurrentContext->GetIndirectAlias();
            if (pIndirectAlias != NULL)
            {
                if (pIndirectAlias->_M_pOriginalCollection == this)
                    return pIndirectAlias;

                //
                // It's still possible that this follows the the pattern used by indirect aliases.  It could be transitive:
                //
                // _TaskCollection rtp;
                // rtp.Schedule( 
                //      { 
                //          _TaskCollection tp;
                //          tp.Schedule(
                //              {
                //                  rtp.Schedule(...);  // <-- this is transitive.
                //                  rtp.Cancel(...);    // <-- this is transitive.
                //              }
                //      });
                //
                // The unfortunate reality of this situation is that indirect aliasing cannot work here (see below).  We need
                // a direct alias.
                //
                // Second generation or older transitivity:  While the indirect alias could be used for this to satisfy the wait,
                // it would lead to deadlock and unexpected behavior if there are out-of-band dependencies between the code after the wait and the
                // whatever we add to the transitive object.  For example,
                //
                // A -> B -> C
                //
                // If C does A.Schedule(x);
                // x == { receive_message(); }
                // and someone in the middle does B.Wait(); send_message();
                //
                // using the indirect alias would deadlock because C would wait on x, B waits on C, and after B waits on C, x is satisfied.
                //
                // Hence -- we must use a direct alias in this case.
                //
            }

            ASSERT(!_IsAlias());

            _TaskCollection *pAlias = pCurrentContext->GetArbitraryAlias(this);
            if (pAlias != NULL)
            {
                //
                // Make certain the alias we are returning to the client is an alias for the task collection and thread we think it is and that it is **NOT**
                // stale.  Stale would imply that either the this pointer was deleted (bad) or that the context underlying the alias was deleted (bad).  In any
                // of these cases, there's an issue with the alias we are returning and the caller will corrupt another thread's data structure.
                //
                ASSERT(pAlias->_M_pOriginalCollection == this && reinterpret_cast<ContextBase *>(pAlias->_M_pOwningContext) == pCurrentContext && !pAlias->_IsStaleAlias());
                return pAlias;
            }

            //
            // At this stage, we are forced to create a direct alias.  
            //
            _TaskCollection *pDirectAlias = new _TaskCollection(this, true);
            pCurrentContext->AddArbitraryAlias(this, pDirectAlias);

            return pDirectAlias;
        }

        return this;
    }

    /// <summary>
    ///     Returns whether the task collection is an alias.
    /// </summary>
    bool _TaskCollection::_IsAlias() const
    {
        return (_M_pOriginalCollection != this);
    }

    /// <summary>
    ///     Returns whether the task collection is an indirect alias.
    /// </summary>
    bool _TaskCollection::_IsIndirectAlias() const
    {
        return (_M_pOriginalCollection != this && (_M_flags & TASKCOLLECTIONFLAG_ALIAS_IS_INDIRECT) != 0);
    }

    /// <summary>
    ///     Returns whether the task collection has a direct alias
    /// </summary>
    bool _TaskCollection::_HasDirectAlias() const
    {
        return (_M_pOriginalCollection->_M_pNextAlias != NULL);
    }

    /// <summary>
    ///     Returns whether the task collection is a direct alias.
    /// </summary>
    bool _TaskCollection::_IsDirectAlias() const
    {
        return (_M_pOriginalCollection != this && (_M_flags & TASKCOLLECTIONFLAG_ALIAS_IS_INDIRECT) == 0);
    }

    /// <summary>
    ///     Returns whether this task collection is marked for abnormal exit.
    /// </summary>
    bool _TaskCollection::_IsMarkedForAbnormalExit() const
    {

⌨️ 快捷键说明

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