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.
263 lines
6.2 KiB
C++
263 lines
6.2 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <eathread/internal/config.h>
|
|
#include "eathread/internal/eathread_global.h"
|
|
#include <eathread/eathread_thread.h>
|
|
#include <eathread/eathread_mutex.h>
|
|
#include <new> // include new for placement new operator
|
|
|
|
#if !EA_THREADS_AVAILABLE
|
|
// Do nothing
|
|
#elif EA_USE_CPP11_CONCURRENCY
|
|
#include "cpp11/eathread_thread_cpp11.cpp"
|
|
#elif defined(EA_PLATFORM_SONY)
|
|
#include "sony/eathread_thread_sony.cpp"
|
|
#elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
|
|
#include "unix/eathread_thread_unix.cpp"
|
|
#elif defined(EA_PLATFORM_MICROSOFT)
|
|
#include "pc/eathread_thread_pc.cpp"
|
|
#endif
|
|
|
|
|
|
|
|
namespace EA
|
|
{
|
|
namespace Thread
|
|
{
|
|
extern Allocator* gpAllocator;
|
|
}
|
|
}
|
|
|
|
|
|
EA::Thread::Thread* EA::Thread::ThreadFactory::CreateThread()
|
|
{
|
|
if(gpAllocator)
|
|
return new(gpAllocator->Alloc(sizeof(EA::Thread::Thread))) EA::Thread::Thread;
|
|
else
|
|
return new EA::Thread::Thread;
|
|
}
|
|
|
|
void EA::Thread::ThreadFactory::DestroyThread(EA::Thread::Thread* pThread)
|
|
{
|
|
if(gpAllocator)
|
|
{
|
|
pThread->~Thread();
|
|
gpAllocator->Free(pThread);
|
|
}
|
|
else
|
|
delete pThread;
|
|
}
|
|
|
|
size_t EA::Thread::ThreadFactory::GetThreadSize()
|
|
{
|
|
return sizeof(EA::Thread::Thread);
|
|
}
|
|
|
|
EA::Thread::Thread* EA::Thread::ThreadFactory::ConstructThread(void* pMemory)
|
|
{
|
|
return new(pMemory) EA::Thread::Thread;
|
|
}
|
|
|
|
void EA::Thread::ThreadFactory::DestructThread(EA::Thread::Thread* pThread)
|
|
{
|
|
pThread->~Thread();
|
|
}
|
|
|
|
EA::Thread::ThreadEnumData::ThreadEnumData()
|
|
: mpThreadDynamicData(NULL)
|
|
{
|
|
}
|
|
|
|
EA::Thread::ThreadEnumData::~ThreadEnumData()
|
|
{
|
|
Release();
|
|
}
|
|
|
|
void EA::Thread::ThreadEnumData::Release()
|
|
{
|
|
if(mpThreadDynamicData)
|
|
{
|
|
mpThreadDynamicData->Release();
|
|
mpThreadDynamicData = NULL;
|
|
}
|
|
}
|
|
|
|
extern const size_t kMaxThreadDynamicDataCount;
|
|
EATHREAD_GLOBALVARS_EXTERN_INSTANCE;
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
size_t EA::Thread::EnumerateThreads(ThreadEnumData* pDataArray, size_t dataArrayCapacity)
|
|
{
|
|
size_t requiredCount = 0;
|
|
|
|
if(dataArrayCapacity > EA::Thread::kMaxThreadDynamicDataCount)
|
|
dataArrayCapacity = EA::Thread::kMaxThreadDynamicDataCount;
|
|
|
|
EATHREAD_GLOBALVARS.gThreadDynamicMutex.Lock();
|
|
for(size_t i(0); i < EA::Thread::kMaxThreadDynamicDataCount; i++)
|
|
{
|
|
if(EATHREAD_GLOBALVARS.gThreadDynamicDataAllocated[i].GetValue() != 0)
|
|
{
|
|
if(requiredCount < dataArrayCapacity)
|
|
{
|
|
pDataArray[requiredCount].mpThreadDynamicData = (EAThreadDynamicData*)(void*)EATHREAD_GLOBALVARS.gThreadDynamicData[i];
|
|
pDataArray[requiredCount].mpThreadDynamicData->AddRef();
|
|
}
|
|
requiredCount++;
|
|
}
|
|
}
|
|
EATHREAD_GLOBALVARS.gThreadDynamicMutex.Unlock();
|
|
|
|
return requiredCount;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// non-threaded implementation
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if !EA_THREADS_AVAILABLE
|
|
|
|
// If mulitithreading support is not available, we can't implement anything
|
|
// here that works. All we do is define a null implementation that links
|
|
// but fails all operations.
|
|
|
|
|
|
EA::Thread::ThreadParameters::ThreadParameters()
|
|
: mpStack(NULL),
|
|
mnStackSize(0),
|
|
mnPriority(kThreadPriorityDefault),
|
|
mnProcessor(kProcessorDefault),
|
|
mpName(""),
|
|
mbDisablePriorityBoost(false)
|
|
{
|
|
}
|
|
|
|
|
|
EA::Thread::Thread::Thread()
|
|
{
|
|
mThreadData.mpData = NULL;
|
|
}
|
|
|
|
|
|
EA::Thread::Thread::Thread(const Thread& /*t*/)
|
|
{
|
|
}
|
|
|
|
|
|
EA::Thread::Thread& EA::Thread::Thread::operator=(const Thread& /*t*/)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
|
|
EA::Thread::Thread::~Thread()
|
|
{
|
|
}
|
|
|
|
|
|
EA::Thread::RunnableFunctionUserWrapper EA::Thread::Thread::sGlobalRunnableFunctionUserWrapper = NULL;
|
|
EA::Thread::RunnableClassUserWrapper EA::Thread::Thread::sGlobalRunnableClassUserWrapper = NULL;
|
|
EA::Thread::AtomicInt32 EA::Thread::Thread::sDefaultProcessor = kProcessorAny;
|
|
EA::Thread::AtomicUint64 EA::Thread::Thread::sDefaultProcessorMask = UINT64_C(0xffffffffffffffff);
|
|
|
|
|
|
EA::Thread::RunnableFunctionUserWrapper EA::Thread::Thread::GetGlobalRunnableFunctionUserWrapper()
|
|
{
|
|
return sGlobalRunnableFunctionUserWrapper;
|
|
}
|
|
|
|
void EA::Thread::Thread::SetGlobalRunnableFunctionUserWrapper(EA::Thread::RunnableFunctionUserWrapper pUserWrapper)
|
|
{
|
|
if (sGlobalRunnableFunctionUserWrapper != NULL)
|
|
{
|
|
// Can only be set once in entire game.
|
|
EAT_ASSERT(false);
|
|
}
|
|
else
|
|
sGlobalRunnableFunctionUserWrapper = pUserWrapper;
|
|
}
|
|
|
|
EA::Thread::RunnableClassUserWrapper EA::Thread::Thread::GetGlobalRunnableClassUserWrapper()
|
|
{
|
|
return sGlobalRunnableClassUserWrapper;
|
|
}
|
|
|
|
void EA::Thread::Thread::SetGlobalRunnableClassUserWrapper(EA::Thread::RunnableClassUserWrapper pUserWrapper)
|
|
{
|
|
if (sGlobalRunnableClassUserWrapper != NULL)
|
|
{
|
|
// Can only be set once in entire game.
|
|
EAT_ASSERT(false);
|
|
}
|
|
else
|
|
sGlobalRunnableClassUserWrapper = pUserWrapper;
|
|
}
|
|
|
|
|
|
EA::Thread::ThreadId EA::Thread::Thread::Begin(RunnableFunction /*pFunction*/, void* /*pContext*/, const ThreadParameters* /*pTP*/, RunnableFunctionUserWrapper /*pUserWrapper*/)
|
|
{
|
|
return kThreadIdInvalid;
|
|
}
|
|
|
|
|
|
EA::Thread::ThreadId EA::Thread::Thread::Begin(IRunnable* /*pRunnable*/, void* /*pContext*/, const ThreadParameters* /*pTP*/, RunnableClassUserWrapper /*pUserWrapper*/)
|
|
{
|
|
return kThreadIdInvalid;
|
|
}
|
|
|
|
|
|
EA::Thread::Thread::Status EA::Thread::Thread::WaitForEnd(const ThreadTime& /*timeoutAbsolute*/, intptr_t* /*pThreadReturnValue*/)
|
|
{
|
|
return kStatusNone;
|
|
}
|
|
|
|
|
|
EA::Thread::Thread::Status EA::Thread::Thread::GetStatus(intptr_t* /*pThreadReturnValue*/) const
|
|
{
|
|
return kStatusNone;
|
|
}
|
|
|
|
|
|
EA::Thread::ThreadId EA::Thread::Thread::GetId() const
|
|
{
|
|
return (ThreadId)kThreadIdInvalid;
|
|
}
|
|
|
|
|
|
int EA::Thread::Thread::GetPriority() const
|
|
{
|
|
return kThreadPriorityUnknown;
|
|
}
|
|
|
|
|
|
bool EA::Thread::Thread::SetPriority(int /*nPriority*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
void EA::Thread::Thread::SetProcessor(int /*nProcessor*/)
|
|
{
|
|
}
|
|
|
|
|
|
void EA::Thread::Thread::Wake()
|
|
{
|
|
}
|
|
|
|
|
|
const char* EA::Thread::Thread::GetName() const
|
|
{
|
|
return "";
|
|
}
|
|
|
|
|
|
void EA::Thread::Thread::SetName(const char* /*pName*/)
|
|
{
|
|
}
|
|
|
|
#endif // !EA_THREADS_AVAILABLE
|
|
|