VirtualBox

Changeset 36524 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 4, 2011 12:46:30 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
70945
Message:

IPRT-C++: add a thread-safe variant of the generic list class

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/testcase/tstIprtList.cpp

    r36508 r36524  
    2828*   Header Files                                                               *
    2929*******************************************************************************/
    30 #include <iprt/cpp/list.h>
     30#include <iprt/cpp/mtlist.h>
    3131
    3232#include <iprt/cpp/ministring.h>
     
    153153 * @param   cTestItems  The size of the input data.
    154154 */
    155 template<typename T1, typename T2>
    156 static void test(const char *pcszDesc, T2 paTestData[], size_t cTestItems)
     155template<template <class, typename> class L, typename T1, typename T2, typename T3>
     156static void test1(const char *pcszDesc, T3 paTestData[], size_t cTestItems)
    157157{
    158158    RTTestISubF("%s with size of %u (items=%u)", pcszDesc, sizeof(T1), cTestItems);
     
    163163
    164164    /* Create a test list */
    165     iprt::list<T1> testList;
    166 
     165    L<T1, T2> testList;
     166
     167    const size_t defCap = L<T1, T2>::DefaultCapacity;
    167168    RTTESTI_CHECK(testList.isEmpty());
    168169    RTTESTI_CHECK(testList.size()     == 0);
    169     RTTESTI_CHECK(testList.capacity() == iprt::list<T1>::DefaultCapacity);
     170    RTTESTI_CHECK(testList.capacity() == defCap);
    170171
    171172    /*
     
    218219     * Copy operator
    219220     */
    220     iprt::list<T1> testList2(testList);
     221    L<T1, T2> testList2(testList);
    221222
    222223    /* Check that all is correctly appended. */
     
    228229     * "=" operator
    229230     */
    230     iprt::list<T1> testList3;
     231    L<T1, T2> testList3;
    231232    testList3 = testList;
    232233
     
    343344    RTTESTI_CHECK_RETV(testList.isEmpty());
    344345    RTTESTI_CHECK_RETV(testList.size() == 0);
    345     RTTESTI_CHECK(testList.capacity()  == iprt::list<T1>::DefaultCapacity);
    346 }
    347 
     346    RTTESTI_CHECK(testList.capacity()  == defCap);
     347}
     348
     349/* define iprt::list here to see what happens without MT support ;)
     350 * (valgrind is the preferred tool to check). */
     351#define MTTESTLISTTYPE iprt::mtlist
     352#define MTTESTTYPE uint32_t
     353#define MTTESTITEMS 1000
     354
     355/**
     356 * Thread for prepending items to a shared list.
     357 *
     358 * @param   hSelf       The thread handle.
     359 * @param   pvUser      The provided user data.
     360 */
     361DECLCALLBACK(int) mttest1(RTTHREAD hSelf, void *pvUser)
     362{
     363    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
     364
     365    /* Prepend new items at the start of the list. */
     366    for (size_t i = 0; i < MTTESTITEMS; ++i)
     367        pTestList->prepend(0x0);
     368
     369    return VINF_SUCCESS;
     370}
     371
     372/**
     373 * Thread for appending items to a shared list.
     374 *
     375 * @param   hSelf       The thread handle.
     376 * @param   pvUser      The provided user data.
     377 */
     378DECLCALLBACK(int) mttest2(RTTHREAD hSelf, void *pvUser)
     379{
     380    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
     381
     382    /* Append new items at the end of the list. */
     383    for (size_t i = 0; i < MTTESTITEMS; ++i)
     384        pTestList->append(0xFFFFFFFF);
     385
     386    return VINF_SUCCESS;
     387}
     388
     389/**
     390 * Thread for inserting items to a shared list.
     391 *
     392 * @param   hSelf       The thread handle.
     393 * @param   pvUser      The provided user data.
     394 */
     395DECLCALLBACK(int) mttest3(RTTHREAD hSelf, void *pvUser)
     396{
     397    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
     398
     399    /* Insert new items in the middle of the list. */
     400    for (size_t i = 0; i < MTTESTITEMS; ++i)
     401        pTestList->insert(pTestList->size() / 2, 0xF0F0F0F0);
     402
     403    return VINF_SUCCESS;
     404}
     405
     406/**
     407 * Thread for reading items from a shared list.
     408 *
     409 * @param   hSelf       The thread handle.
     410 * @param   pvUser      The provided user data.
     411 */
     412DECLCALLBACK(int) mttest4(RTTHREAD hSelf, void *pvUser)
     413{
     414    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
     415
     416    MTTESTTYPE a;
     417    /* Try to read C items from random places. */
     418    for (size_t i = 0; i < MTTESTITEMS; ++i)
     419    {
     420        /* Make sure there is at least one item in the list. */
     421        while (pTestList->isEmpty()) {};
     422        a = pTestList->at(RTRandU32Ex(0, pTestList->size() - 1));
     423    }
     424
     425    return VINF_SUCCESS;
     426}
     427
     428/**
     429 * Thread for replacing items in a shared list.
     430 *
     431 * @param   hSelf       The thread handle.
     432 * @param   pvUser      The provided user data.
     433 */
     434DECLCALLBACK(int) mttest5(RTTHREAD hSelf, void *pvUser)
     435{
     436    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
     437
     438    /* Try to replace C items from random places. */
     439    for (size_t i = 0; i < MTTESTITEMS; ++i)
     440    {
     441        /* Make sure there is at least one item in the list. */
     442        while (pTestList->isEmpty()) {};
     443        pTestList->replace(RTRandU32Ex(0, pTestList->size() - 1), 0xFF00FF00);
     444    }
     445
     446    return VINF_SUCCESS;
     447}
     448
     449/**
     450 * Thread for erasing items from a shared list.
     451 *
     452 * @param   hSelf       The thread handle.
     453 * @param   pvUser      The provided user data.
     454 */
     455DECLCALLBACK(int) mttest6(RTTHREAD hSelf, void *pvUser)
     456{
     457    MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
     458
     459    /* Try to delete items from random places. */
     460    for (size_t i = 0; i < MTTESTITEMS; ++i)
     461    {
     462        /* Make sure there is at least one item in the list. */
     463        while (pTestList->isEmpty()) {};
     464        pTestList->removeAt(RTRandU32Ex(0, pTestList->size() - 1));
     465    }
     466
     467    return VINF_SUCCESS;
     468}
     469
     470/**
     471 * Does a multi-threading list test. Several list additions, reading, replacing
     472 * and erasing are done simultaneous.
     473 *
     474 */
     475static void test2()
     476{
     477    RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS);
     478
     479    RTTHREAD hThread1, hThread2, hThread3, hThread4, hThread5, hThread6;
     480    int rc = VINF_SUCCESS;
     481
     482    MTTESTLISTTYPE<MTTESTTYPE> testList;
     483    rc = RTThreadCreate(&hThread1, &mttest1, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest1");
     484    AssertRC(rc);
     485    rc = RTThreadCreate(&hThread2, &mttest2, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest2");
     486    AssertRC(rc);
     487    rc = RTThreadCreate(&hThread3, &mttest3, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest3");
     488    AssertRC(rc);
     489    rc = RTThreadCreate(&hThread4, &mttest4, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest4");
     490    AssertRC(rc);
     491    rc = RTThreadCreate(&hThread5, &mttest5, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest5");
     492    AssertRC(rc);
     493    rc = RTThreadCreate(&hThread6, &mttest6, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest6");
     494    AssertRC(rc);
     495
     496    rc = RTThreadWait(hThread1, RT_INDEFINITE_WAIT, 0);
     497    AssertRC(rc);
     498    rc = RTThreadWait(hThread2, RT_INDEFINITE_WAIT, 0);
     499    AssertRC(rc);
     500    rc = RTThreadWait(hThread3, RT_INDEFINITE_WAIT, 0);
     501    AssertRC(rc);
     502    rc = RTThreadWait(hThread4, RT_INDEFINITE_WAIT, 0);
     503    AssertRC(rc);
     504    rc = RTThreadWait(hThread5, RT_INDEFINITE_WAIT, 0);
     505    AssertRC(rc);
     506    rc = RTThreadWait(hThread6, RT_INDEFINITE_WAIT, 0);
     507    AssertRC(rc);
     508
     509    RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2);
     510    for (size_t i = 0; i < testList.size(); ++i)
     511    {
     512        uint32_t a = testList.at(i);
     513        RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00);
     514    }
     515}
    348516
    349517int main()
     
    371539    for (size_t i = 0; i < RT_ELEMENTS(au8TestInts); ++i)
    372540        au8TestInts[i] = (uint8_t)RTRandU32Ex(0, UINT8_MAX);
    373     test<uint8_t, uint8_t>("Native type", au8TestInts, RT_ELEMENTS(au8TestInts));
     541    test1<iprt::list,   uint8_t, uint8_t, uint8_t>("ST: Native type", au8TestInts, RT_ELEMENTS(au8TestInts));
     542    test1<iprt::mtlist, uint8_t, uint8_t, uint8_t>("MT: Native type", au8TestInts, RT_ELEMENTS(au8TestInts));
    374543
    375544    uint16_t au16TestInts[s_cTestCount];
    376545    for (size_t i = 0; i < RT_ELEMENTS(au16TestInts); ++i)
    377546        au16TestInts[i] = (uint16_t)RTRandU32Ex(0, UINT16_MAX);
    378     test<uint16_t, uint16_t>("Native type", au16TestInts, RT_ELEMENTS(au16TestInts));
     547    test1<iprt::list,   uint16_t, uint16_t, uint16_t>("ST: Native type", au16TestInts, RT_ELEMENTS(au16TestInts));
     548    test1<iprt::mtlist, uint16_t, uint16_t, uint16_t>("MT: Native type", au16TestInts, RT_ELEMENTS(au16TestInts));
    379549
    380550    uint32_t au32TestInts[s_cTestCount];
    381551    for (size_t i = 0; i < RT_ELEMENTS(au32TestInts); ++i)
    382552        au32TestInts[i] = RTRandU32();
    383     test<uint32_t, uint32_t>("Native type", au32TestInts, RT_ELEMENTS(au32TestInts));
     553    test1<iprt::list,   uint32_t, uint32_t, uint32_t>("ST: Native type", au32TestInts, RT_ELEMENTS(au32TestInts));
     554    test1<iprt::mtlist, uint32_t, uint32_t, uint32_t>("MT: Native type", au32TestInts, RT_ELEMENTS(au32TestInts));
    384555
    385556    /*
     
    389560    for (size_t i = 0; i < RT_ELEMENTS(au64TestInts); ++i)
    390561        au64TestInts[i] = RTRandU64();
    391     test<uint64_t, uint64_t>("Specialized type", au64TestInts, RT_ELEMENTS(au64TestInts));
     562    test1<iprt::list,   uint64_t, uint64_t, uint64_t>("ST: Specialized type", au64TestInts, RT_ELEMENTS(au64TestInts));
     563    test1<iprt::mtlist, uint64_t, uint64_t, uint64_t>("MT: Specialized type", au64TestInts, RT_ELEMENTS(au64TestInts));
    392564
    393565    /*
    394566     * Big size type (translate to internal pointer list).
    395567     */
    396     test<iprt::MiniString, const char *>("Class type", g_apszTestStrings, RT_ELEMENTS(g_apszTestStrings));
     568    test1<iprt::list,   iprt::MiniString, iprt::MiniString*, const char *>("ST: Class type", g_apszTestStrings, RT_ELEMENTS(g_apszTestStrings));
     569    test1<iprt::mtlist, iprt::MiniString, iprt::MiniString*, const char *>("MT: Class type", g_apszTestStrings, RT_ELEMENTS(g_apszTestStrings));
     570
     571    /*
     572     * Multi-threading test.
     573     */
     574    test2();
    397575
    398576    /*
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