| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- ///////////////////////////////////////////////////////////////////////////////
- // Copyright (c) Electronic Arts Inc. All rights reserved.
- ///////////////////////////////////////////////////////////////////////////////
- #include "TestThread.h"
- #include <EATest/EATest.h>
- #include <eathread/eathread_thread.h>
- #include <eathread/eathread_mutex.h>
- #include <eathread/eathread_barrier.h>
- #include <stdlib.h>
- using namespace EA::Thread;
- const int kMaxConcurrentThreadCount = EATHREAD_MAX_CONCURRENT_THREAD_COUNT;
- struct BT_WorkData
- {
- Barrier* mpBarrier;
- int mnSleepTime;
- AtomicInt32 mnErrorCount;
- BT_WorkData(Barrier* pBarrier = NULL, int nSleepTime = 0)
- : mpBarrier(pBarrier), mnSleepTime(nSleepTime), mnErrorCount(0) {}
- };
- static intptr_t BT_ConsumerFunction(void* pvWorkData)
- {
- int nErrorCount = 0;
- BT_WorkData* pWorkData = (BT_WorkData*)pvWorkData;
- const ThreadId threadId = GetThreadId();
- EA::UnitTest::ReportVerbosity(1, "Barrier consumer test function created: %s\n", EAThreadThreadIdToString(threadId));
- // Here we would actually do the job, but printing 'job done' is enough in itself.
- ThreadSleep((ThreadTime)pWorkData->mnSleepTime);
- EA::UnitTest::ReportVerbosity(1, "Job done by thread %s.\n", EAThreadThreadIdToString(threadId));
- EA::UnitTest::ReportVerbosity(1, "Start synchronizing by thread %s.\n", EAThreadThreadIdToString(threadId));
- const Barrier::Result result = pWorkData->mpBarrier->Wait(GetThreadTime() + 10000);
- if(result == Barrier::kResultPrimary)
- {
- // This is the first thread to be released: call producer function
- EA::UnitTest::ReportVerbosity(1, "Serial execution at Barrier by thread %s\n", EAThreadThreadIdToString(threadId));
- }
- else if(result == Barrier::kResultTimeout)
- {
- EA::UnitTest::Report("Barrier time-out by thread %s\n", EAThreadThreadIdToString(threadId));
- nErrorCount++;
- }
- else if(result == Barrier::kResultError)
- {
- EA::UnitTest::Report("Barrier error in thread %s\n", EAThreadThreadIdToString(threadId));
- nErrorCount++;
- }
- pWorkData->mnErrorCount += nErrorCount;
- ThreadSleep((ThreadTime)pWorkData->mnSleepTime);
- EA::UnitTest::ReportVerbosity(1, "Job synchronized by thread %s.\n", EAThreadThreadIdToString(threadId));
- return 0;
- }
- static intptr_t BT_ConsumerFunction2(void * pvWorkData)
- {
- ((Barrier*)pvWorkData)->Wait();
- ((Barrier*)pvWorkData)->Wait();
- return 0;
- }
- int TestThreadBarrier()
- {
- int nErrorCount(0);
- #if EA_THREADS_AVAILABLE
- {
- Thread::Status status;
- const int kThreadCount(kMaxConcurrentThreadCount - 1);
- BT_WorkData workData[kThreadCount];
- Thread threads[kThreadCount];
- ThreadId threadId[kThreadCount];
- Barrier barrier(kThreadCount);
- int i;
- for(i = 0; i < kThreadCount; i++)
- {
- workData[i].mpBarrier = &barrier;
- workData[i].mnSleepTime = (i + 1) * 500;
- }
- for(i = 0; i < kThreadCount; i++)
- {
- threadId[i] = threads[i].Begin(BT_ConsumerFunction, &workData[i]);
- EATEST_VERIFY_MSG(threadId[i] != kThreadIdInvalid, "Barrier/Thread failure: Couldn't create thread.");
- }
- EA::UnitTest::ThreadSleepRandom(2000, 2000);
- for(i = 0; i < kThreadCount; i++)
- {
- if(threadId[i] != kThreadIdInvalid)
- {
- status = threads[i].WaitForEnd(GetThreadTime() + 30000);
- EATEST_VERIFY_MSG(status != Thread::kStatusRunning, "Barrier/Thread failure.");
- }
- nErrorCount += workData[i].mnErrorCount;
- }
- }
- {
- Thread threads[2];
- ThreadId threadId[2];
- Barrier barrier(2);
- Thread::Status status;
- threadId[0] = threads[0].Begin(BT_ConsumerFunction2, &barrier);
- EATEST_VERIFY_MSG(threadId[0] != kThreadIdInvalid, "Barrier/Thread failure: Couldn't create thread.");
- threadId[1] = threads[1].Begin(BT_ConsumerFunction2, &barrier);
- EATEST_VERIFY_MSG(threadId[1] != kThreadIdInvalid, "Barrier/Thread failure: Couldn't create thread.");
- if(threadId[0] != kThreadIdInvalid)
- {
- status = threads[0].WaitForEnd();
- EATEST_VERIFY_MSG(status != Thread::kStatusRunning, "Barrier/Thread failure.");
- }
- if(threadId[1] != kThreadIdInvalid)
- {
- status = threads[1].WaitForEnd();
- EATEST_VERIFY_MSG(status != Thread::kStatusRunning, "Barrier/Thread failure.");
- }
- }
- #endif
- return nErrorCount;
- }
|