VirtualBox

Changeset 93709 in vbox


Ignore:
Timestamp:
Feb 11, 2022 11:09:11 PM (3 years ago)
Author:
vboxsync
Message:

IPRT/hardavl: Added the right-to-left enumerator. Mark methods as noexcept. bugref:10093

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/cpp/hardavlrange.h

    r93695 r93709  
    128128     * Read an index value trying to prevent the compiler from re-reading it.
    129129     */
    130     DECL_FORCE_INLINE(uint32_t) readIdx(uint32_t volatile *pidx)
     130    DECL_FORCE_INLINE(uint32_t) readIdx(uint32_t volatile *pidx) RT_NOEXCEPT
    131131    {
    132132        uint32_t idx = *pidx;
     
    135135    }
    136136
    137 
    138     RTCHardAvlRangeTree()
     137    RTCHardAvlRangeTree() RT_NOEXCEPT
    139138        : m_idxRoot(0)
    140139        , m_cErrors(0)
    141140    { }
    142141
    143     RTCHardAvlRangeTree(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator)
    144         : m_idxRoot(a_pAllocator->kNilIndex)
    145         , m_cErrors(0)
    146     { }
     142    RTCHardAvlRangeTree(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator) RT_NOEXCEPT
     143    {
     144        initWithAllocator(a_pAllocator);
     145    }
     146
     147    void initWithAllocator(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator) RT_NOEXCEPT
     148    {
     149        m_idxRoot = a_pAllocator->kNilIndex;
     150        m_cErrors = 0;
     151    }
    147152
    148153    /**
     
    169174     * @endcode
    170175     */
    171     int insert(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, NodeType *a_pNode)
     176    int insert(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, NodeType *a_pNode) RT_NOEXCEPT
    172177    {
    173178        KeyType const Key     = a_pNode->Key;
     
    269274     * @endcode
    270275     */
    271     int remove(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key, NodeType **a_ppRemoved)
     276    int remove(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key, NodeType **a_ppRemoved) RT_NOEXCEPT
    272277    {
    273278        *a_ppRemoved = NULL;
     
    406411     * @param     a_ppFound     Where to return the pointer to the node.
    407412     */
    408     int lookup(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key, NodeType **a_ppFound)
     413    int lookup(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key, NodeType **a_ppFound) RT_NOEXCEPT
    409414    {
    410415        *a_ppFound = NULL;
     
    475480     * @param     a_pfnCallBack Pointer to callback function.
    476481     * @param     a_pvUser      Callback user argument.
     482     *
     483     * @note      This is very similar code to doWithAllFromRight() and destroy().
    477484     */
    478     int doWithAllFromLeft(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, PFNCALLBACK a_pfnCallBack, void *a_pvUser)
     485    int doWithAllFromLeft(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator,
     486                          PFNCALLBACK a_pfnCallBack, void *a_pvUser) RT_NOEXCEPT
    479487    {
    480488        NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
     
    575583
    576584    /**
     585     * Iterates thru all nodes in the tree from right (larger) to left (smaller).
     586     *
     587     * @returns   IPRT status code.
     588     *
     589     * @param     a_pAllocator  Pointer to the allocator.
     590     * @param     a_pfnCallBack Pointer to callback function.
     591     * @param     a_pvUser      Callback user argument.
     592     *
     593     * @note      This is very similar code to doWithAllFromLeft() and destroy().
     594     */
     595    int doWithAllFromRight(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator,
     596                           PFNCALLBACK a_pfnCallBack, void *a_pvUser) RT_NOEXCEPT
     597    {
     598        NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
     599        AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
     600                            m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
     601        if (!pNode)
     602            return VINF_SUCCESS;
     603
     604        /*
     605         * We simulate recursive calling here.  For safety reasons, we do not
     606         * pop before going down the right tree like the original code did.
     607         */
     608        uint32_t  cNodesLeft = a_pAllocator->m_cNodes;
     609        NodeType *apEntries[kMaxStack];
     610        uint8_t   abState[kMaxStack];
     611        unsigned  cEntries = 1;
     612        abState[0]   = 0;
     613        apEntries[0] = pNode;
     614        while (cEntries > 0)
     615        {
     616            pNode = apEntries[cEntries - 1];
     617            switch (abState[cEntries - 1])
     618            {
     619                /* Go right. */
     620                case 0:
     621                {
     622                    abState[cEntries - 1] = 1;
     623
     624                    NodeType * const pRightNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxRight));
     625                    AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightNode),
     626                                        ("idxRight=%#x pRightNode=%p\n", pNode->idxRight, pRightNode),
     627                                        m_cErrors++, a_pAllocator->ptrErrToStatus(pRightNode));
     628                    if (pRightNode)
     629                    {
     630#if RT_GNUC_PREREQ_EX(4,7, 1) /* 32-bit 4.4.7 has trouble, dunno when it started working exactly */
     631                        AssertCompile(kMaxStack > 6);
     632#endif
     633                        AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
     634                                            ("%p[%#x] %p %p %p %p %p %p\n", pRightNode, pNode->idxRight, apEntries[kMaxStack - 1],
     635                                             apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
     636                                             apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
     637                                            m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
     638                        apEntries[cEntries] = pRightNode;
     639                        abState[cEntries]   = 0;
     640                        cEntries++;
     641
     642                        AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
     643                        cNodesLeft--;
     644                        break;
     645                    }
     646                    RT_FALL_THROUGH();
     647                }
     648
     649                /* center then left. */
     650                case 1:
     651                {
     652                    abState[cEntries - 1] = 2;
     653
     654                    RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, NULL, 0);
     655
     656                    int rc = a_pfnCallBack(pNode, a_pvUser);
     657                    if (rc != VINF_SUCCESS)
     658                        return rc;
     659
     660                    NodeType * const pLeftNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxLeft));
     661                    AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNode),
     662                                        ("idxLeft=%#x pLeftNode=%p\n", pNode->idxLeft, pLeftNode),
     663                                        m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftNode));
     664                    if (pLeftNode)
     665                    {
     666#if RT_GNUC_PREREQ_EX(4,7, 1) /* 32-bit 4.4.7 has trouble, dunno when it started working exactly */
     667                        AssertCompile(kMaxStack > 6);
     668#endif
     669                        AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
     670                                            ("%p[%#x] %p %p %p %p %p %p\n", pLeftNode, pNode->idxLeft, apEntries[kMaxStack - 1],
     671                                             apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
     672                                             apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
     673                                            m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
     674                        apEntries[cEntries] = pLeftNode;
     675                        abState[cEntries]   = 0;
     676                        cEntries++;
     677
     678                        AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
     679                        cNodesLeft--;
     680                        break;
     681                    }
     682                    RT_FALL_THROUGH();
     683                }
     684
     685                default:
     686                    /* pop it. */
     687                    cEntries -= 1;
     688                    break;
     689            }
     690        }
     691        return VINF_SUCCESS;
     692    }
     693
     694    /**
    577695     * A callback for destroy to do additional cleanups before the node is freed.
    578696     *
     
    599717     * @note      This is mostly the same code as the doWithAllFromLeft().
    600718     */
    601     int destroy(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, PFNDESTROYCALLBACK a_pfnCallBack = NULL, void *a_pvUser = NULL)
     719    int destroy(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator,
     720                PFNDESTROYCALLBACK a_pfnCallBack = NULL, void *a_pvUser = NULL) RT_NOEXCEPT
    602721    {
    603722        NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
     
    707826     * @retval UINT8_MAX if bogus tree.
    708827     */
    709     uint8_t getHeight(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator)
     828    uint8_t getHeight(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator) RT_NOEXCEPT
    710829    {
    711830        NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
     
    719838#ifdef RT_STRICT
    720839
    721     static void dumpStack(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, HardAvlStack const *pStack)
     840    static void dumpStack(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, HardAvlStack const *pStack) RT_NOEXCEPT
    722841    {
    723842        uint32_t const * const *paidx = pStack->apidxEntries;
     
    735854
    736855    static void printTree(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, uint32_t a_idxRoot,
    737                           unsigned a_uLevel = 0, unsigned a_uMaxLevel = 8, const char *a_pszDir = "")
     856                          unsigned a_uLevel = 0, unsigned a_uMaxLevel = 8, const char *a_pszDir = "") RT_NOEXCEPT
    738857    {
    739858        if (a_idxRoot == a_pAllocator->kNilIndex)
     
    811930     * @internal
    812931     */
    813     int i_rebalance(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, HardAvlStack *a_pStack, bool a_fLog = false)
     932    int i_rebalance(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, HardAvlStack *a_pStack, bool a_fLog = false) RT_NOEXCEPT
    814933    {
    815934        RT_NOREF(a_fLog);
  • trunk/src/VBox/Runtime/testcase/tstRTAvl.cpp

    r93694 r93709  
    11241124
    11251125
     1126static DECLCALLBACK(int) hardAvlRangeTreeGCPhysEnumCallbackDescBy4(TESTNODE *pNode, void *pvUser)
     1127{
     1128    PRTGCPHYS pExpect = (PRTGCPHYS)pvUser;
     1129    if (pNode->Key != *pExpect)
     1130        RTTestIFailed("Key=%RGp, expected %RGp\n", pNode->Key, *pExpect);
     1131    *pExpect = pNode->Key - 4;
     1132    return VINF_SUCCESS;
     1133}
     1134
     1135
    11261136static DECLCALLBACK(int) hardAvlRangeTreeGCPhysEnumCallbackCount(TESTNODE *pNode, void *pvUser)
    11271137{
     
    13161326        if (rc != VINF_SUCCESS)
    13171327            RTTestIFailed("enumeration after linear insert failed: %Rrc", rc);
     1328
     1329        Expect -= 4;
     1330        rc = Tree.doWithAllFromRight(&Allocator, hardAvlRangeTreeGCPhysEnumCallbackDescBy4, &Expect);
     1331        if (rc != VINF_SUCCESS)
     1332            RTTestIFailed("enumeration after linear insert failed: %Rrc", rc);
    13181333    }
    13191334
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette