mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
DirtySDK (EA's Dirty Sockets library) will be used for the LiveAPI implementation, and depends on: EABase, EAThread.
158 lines
4.2 KiB
C++
158 lines
4.2 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// 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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|