static int tstHandleTableTest1(uint32_t uBase, uint32_t cMax, uint32_t cDelta, uint32_t cUnitsPerDot, bool fCallbacks, uint32_t fFlags)
{
    const char *pszWithCtx = fFlags & RTHANDLETABLE_FLAGS_CONTEXT ? "WithCtx" : "";
    uint32_t cRetainerCalls = 0;
    int rc;

    RTPrintf("tstHandleTable: TESTING RTHandleTableCreateEx(, 0");
    if (fFlags & RTHANDLETABLE_FLAGS_LOCKED)    RTPrintf(" | LOCKED");
    if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)   RTPrintf(" | CONTEXT");
    RTPrintf(", %#x, %#x,,)...\n", uBase, cMax);

    RTHANDLETABLE hHT;
    rc = RTHandleTableCreateEx(&hHT, fFlags, uBase, cMax,
                               fCallbacks ? tstHandleTableTest1Retain : NULL,
                               fCallbacks ? &cRetainerCalls : NULL);
    if (RT_FAILURE(rc))
    {
        RTPrintf("\ntstHandleTable: FAILURE - RTHandleTableCreateEx failed, %Rrc!\n", rc);
        return 1;
    }

    /* fill it */
    RTPrintf("tstHandleTable: TESTING   RTHandleTableAlloc%s..", pszWithCtx);
    RTStrmFlush(g_pStdOut);
    uint32_t i = uBase;
    for (;; i++)
    {
        uint32_t h;
        if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
            rc = RTHandleTableAllocWithCtx(hHT, (void *)((uintptr_t)&i + (uintptr_t)i * 4), NULL, &h);
        else
            rc = RTHandleTableAlloc(hHT, (void *)((uintptr_t)&i + (uintptr_t)i * 4), &h);
        if (RT_SUCCESS(rc))
        {
            if (h != i)
            {
                RTPrintf("\ntstHandleTable: FAILURE (%d) - h=%d, expected %d!\n", __LINE__, h, i);
                g_cErrors++;
            }
        }
        else if (rc == VERR_NO_MORE_HANDLES)
        {
            if (i < cMax)
            {
                RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, expected > 65534!\n", __LINE__, i);
                g_cErrors++;
            }
            break;
        }
        else
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, rc=%Rrc!\n", __LINE__, i, rc);
            g_cErrors++;
        }
        if (!(i % cUnitsPerDot))
        {
            RTPrintf(".");
            RTStrmFlush(g_pStdOut);
        }
    }
    uint32_t const c = i;
    RTPrintf(" c=%#x\n", c);
    if (fCallbacks && cRetainerCalls != 0)
    {
        RTPrintf("tstHandleTable: FAILURE (%d) - cRetainerCalls=%#x expected 0!\n", __LINE__, cRetainerCalls);
        g_cErrors++;
    }

    /* look up all the entries */
    RTPrintf("tstHandleTable: TESTING   RTHandleTableLookup%s..", pszWithCtx);
    RTStrmFlush(g_pStdOut);
    cRetainerCalls = 0;
    for (i = uBase; i < c; i++)
    {
        void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)i * 4);
        void *pvObj;
        if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
            pvObj = RTHandleTableLookupWithCtx(hHT, i, NULL);
        else
            pvObj = RTHandleTableLookup(hHT, i);
        if (!pvObj)
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookup%s failed!\n", __LINE__, i, pszWithCtx);
            g_cErrors++;
        }
        else if (pvObj != pvExpect)
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, pvObj=%p expected %p\n", __LINE__, i, pvObj, pvExpect);
            g_cErrors++;
        }
        if (!(i % cUnitsPerDot))
        {
            RTPrintf(".");
            RTStrmFlush(g_pStdOut);
        }
    }
    RTPrintf("\n");
    if (fCallbacks && cRetainerCalls != c - uBase)
    {
        RTPrintf("tstHandleTable: FAILURE (%d) - cRetainerCalls=%#x expected %#x!\n", __LINE__, cRetainerCalls, c - uBase);
        g_cErrors++;
    }

    /* remove all the entries (in order) */
    RTPrintf("tstHandleTable: TESTING   RTHandleTableFree%s..", pszWithCtx);
    RTStrmFlush(g_pStdOut);
    cRetainerCalls = 0;
    for (i = uBase; i < c; i++)
    {
        void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)i * 4);
        void *pvObj;
        if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
            pvObj = RTHandleTableFreeWithCtx(hHT, i, NULL);
        else
            pvObj = RTHandleTableFree(hHT, i);
        if (!pvObj)
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookup%s failed!\n", __LINE__, i, pszWithCtx);
            g_cErrors++;
        }
        else if (pvObj != pvExpect)
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, pvObj=%p expected %p\n", __LINE__, i, pvObj, pvExpect);
            g_cErrors++;
        }
        else if (   fFlags & RTHANDLETABLE_FLAGS_CONTEXT
                    ?  RTHandleTableLookupWithCtx(hHT, i, NULL)
                    :  RTHandleTableLookup(hHT, i))
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookup%s succeeded after free!\n", __LINE__, i, pszWithCtx);
            g_cErrors++;
        }
        if (!(i % cUnitsPerDot))
        {
            RTPrintf(".");
            RTStrmFlush(g_pStdOut);
        }
    }
    RTPrintf("\n");
    if (fCallbacks && cRetainerCalls != c - uBase)
    {
        RTPrintf("tstHandleTable: FAILURE (%d) - cRetainerCalls=%#x expected %#x!\n", __LINE__, cRetainerCalls, c - uBase);
        g_cErrors++;
    }

    /* do a mix of alloc, lookup and free where there is a constant of cDelta handles in the table. */
    RTPrintf("tstHandleTable: TESTING   Alloc,Lookup,Free mix [cDelta=%#x]..", cDelta);
    RTStrmFlush(g_pStdOut);
    for (i = uBase; i < c * 2; i++)
    {
        /* alloc */
        uint32_t hExpect = ((i - uBase) % (c - uBase)) + uBase;
        uint32_t h;
        if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
            rc = RTHandleTableAllocWithCtx(hHT, (void *)((uintptr_t)&i + (uintptr_t)hExpect * 4), NULL, &h);
        else
            rc = RTHandleTableAlloc(hHT, (void *)((uintptr_t)&i + (uintptr_t)hExpect * 4), &h);
        if (RT_FAILURE(rc))
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableAlloc%s: rc=%Rrc!\n", __LINE__, i, pszWithCtx, rc);
            g_cErrors++;
        }
        else if (h != hExpect)
        {
            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableAlloc%s: h=%u hExpect=%u! - abort sub-test\n", __LINE__, i, pszWithCtx, h, hExpect);
            g_cErrors++;
            break;
        }

        if (i >= cDelta + uBase)
        {
            /* lookup */
            for (uint32_t j = i - cDelta; j <= i; j++)
            {
                uint32_t hLookup = ((j - uBase) % (c - uBase)) + uBase;
                void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)hLookup * 4);
                void *pvObj;
                if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
                    pvObj = RTHandleTableLookupWithCtx(hHT, hLookup, NULL);
                else
                    pvObj = RTHandleTableLookup(hHT, hLookup);
                if (pvObj != pvExpect)
                {
                    RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, j=%d, RTHandleTableLookup%s(,%u,): pvObj=%p expected %p!\n",
                             __LINE__, i, j, pszWithCtx, hLookup, pvObj, pvExpect);
                    g_cErrors++;
                }
                else if (   (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
                            &&  RTHandleTableLookupWithCtx(hHT, hLookup, &i))
                {
                    RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, j=%d, RTHandleTableLookupWithCtx: succeeded with bad context\n",
                             __LINE__, i, j);
                    g_cErrors++;
                }
            }

            /* free */
            uint32_t hFree = ((i - uBase - cDelta) % (c - uBase)) + uBase;
            void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)hFree * 4);
            void *pvObj;
            if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
                pvObj = RTHandleTableFreeWithCtx(hHT, hFree, NULL);
            else
                pvObj = RTHandleTableFree(hHT, hFree);
            if (pvObj != pvExpect)
            {
                RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableFree%s: pvObj=%p expected %p!\n",
                         __LINE__, i, pszWithCtx, pvObj, pvExpect);
                g_cErrors++;
            }
            else if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT
                     ?      RTHandleTableLookupWithCtx(hHT, hFree, NULL)
                     ||  RTHandleTableFreeWithCtx(hHT, hFree, NULL)
                     :      RTHandleTableLookup(hHT, hFree)
                     ||  RTHandleTableFree(hHT, hFree))
            {
                RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookup/Free%s: succeeded after free\n",
                         __LINE__, i, pszWithCtx);
                g_cErrors++;
            }
        }
        if (!(i % (cUnitsPerDot * 2)))
        {
            RTPrintf(".");
            RTStrmFlush(g_pStdOut);
        }
    }
    RTPrintf("\n");

    /* finally, destroy the table (note that there are 128 entries in it). */
    cRetainerCalls = 0;
    uint32_t cDeleteCalls = 0;
    rc = RTHandleTableDestroy(hHT,
                              fCallbacks ? tstHandleTableTest1Delete : NULL,
                              fCallbacks ? &cDeleteCalls : NULL);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstHandleTable: FAILURE (%d) - RTHandleTableDestroy failed, %Rrc!\n", __LINE__, rc);
        g_cErrors++;
    }

    return 0;
}
Example #2
0
RTDECL(int) RTHandleTableCreate(PRTHANDLETABLE phHandleTable)
{
    return RTHandleTableCreateEx(phHandleTable, RTHANDLETABLE_FLAGS_LOCKED, 1, 65534, NULL, NULL);
}