/** * Does a multi-threading list test. Several list additions, reading, replacing * and erasing are done simultaneous. * */ static void test2() { RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS); int rc; MTTESTLISTTYPE<MTTESTTYPE> testList; RTTHREAD ahThreads[6]; static PFNRTTHREAD apfnThreads[6] = { MtTest1ThreadProc, MtTest2ThreadProc, MtTest3ThreadProc, MtTest4ThreadProc, MtTest5ThreadProc, MtTest6ThreadProc }; for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) { RTTESTI_CHECK_RC_RETV(RTThreadCreateF(&ahThreads[i], apfnThreads[i], &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest%u", i), VINF_SUCCESS); } uint64_t tsMsDeadline = RTTimeMilliTS() + 60000; for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) { uint64_t tsNow = RTTimeMilliTS(); uint32_t cWait = tsNow > tsMsDeadline ? 5000 : tsMsDeadline - tsNow; RTTESTI_CHECK_RC(RTThreadWait(ahThreads[i], tsNow, NULL), VINF_SUCCESS); } RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2); for (size_t i = 0; i < testList.size(); ++i) { uint32_t a = testList.at(i); RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00); } }
/** * Thread for inserting items to a shared list. * * @param hSelf The thread handle. * @param pvUser The provided user data. */ static DECLCALLBACK(int) MtTest3ThreadProc(RTTHREAD hSelf, void *pvUser) { MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; /* Insert new items in the middle of the list. */ for (size_t i = 0; i < MTTESTITEMS; ++i) pTestList->insert(pTestList->size() / 2, 0xF0F0F0F0); return VINF_SUCCESS; }
/** * Thread for appending items to a shared list. * * @param hSelf The thread handle. * @param pvUser The provided user data. */ static DECLCALLBACK(int) MtTest2ThreadProc(RTTHREAD hSelf, void *pvUser) { MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; /* Append new items at the end of the list. */ for (size_t i = 0; i < MTTESTITEMS; ++i) pTestList->append(0xFFFFFFFF); return VINF_SUCCESS; }
/** * Thread for prepending items to a shared list. * * @param hSelf The thread handle. * @param pvUser The provided user data. */ DECLCALLBACK(int) mttest1(RTTHREAD hSelf, void *pvUser) { MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; /* Prepend new items at the start of the list. */ for (size_t i = 0; i < MTTESTITEMS; ++i) pTestList->prepend(0x0); return VINF_SUCCESS; }
/** * Thread for erasing items from a shared list. * * @param hSelf The thread handle. * @param pvUser The provided user data. */ DECLCALLBACK(int) mttest6(RTTHREAD hSelf, void *pvUser) { MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; /* Try to delete items from random places. */ for (size_t i = 0; i < MTTESTITEMS; ++i) { /* Make sure there is at least one item in the list. */ while (pTestList->isEmpty()) {}; pTestList->removeAt(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1)); } return VINF_SUCCESS; }
/** * Thread for replacing items in a shared list. * * @param hSelf The thread handle. * @param pvUser The provided user data. */ static DECLCALLBACK(int) MtTest5ThreadProc(RTTHREAD hSelf, void *pvUser) { MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser; /* Try to replace C items from random places. */ for (size_t i = 0; i < MTTESTITEMS; ++i) { /* Make sure there is at least one item in the list. */ while (pTestList->isEmpty()) RTThreadYield(); pTestList->replace(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1), 0xFF00FF00); } return VINF_SUCCESS; }
/** * Does a multi-threading list test. Several list additions, reading, replacing * and erasing are done simultaneous. * */ static void test2() { RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS); RTTHREAD hThread1, hThread2, hThread3, hThread4, hThread5, hThread6; int rc = VINF_SUCCESS; MTTESTLISTTYPE<MTTESTTYPE> testList; rc = RTThreadCreate(&hThread1, &mttest1, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest1"); AssertRC(rc); rc = RTThreadCreate(&hThread2, &mttest2, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest2"); AssertRC(rc); rc = RTThreadCreate(&hThread3, &mttest3, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest3"); AssertRC(rc); rc = RTThreadCreate(&hThread4, &mttest4, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest4"); AssertRC(rc); rc = RTThreadCreate(&hThread5, &mttest5, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest5"); AssertRC(rc); rc = RTThreadCreate(&hThread6, &mttest6, &testList, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest6"); AssertRC(rc); rc = RTThreadWait(hThread1, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread2, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread3, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread4, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread5, RT_INDEFINITE_WAIT, 0); AssertRC(rc); rc = RTThreadWait(hThread6, RT_INDEFINITE_WAIT, 0); AssertRC(rc); RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2); for (size_t i = 0; i < testList.size(); ++i) { uint32_t a = testList.at(i); RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00); } }