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.
231 lines
6.9 KiB
C++
231 lines
6.9 KiB
C++
/*H********************************************************************************/
|
|
/*!
|
|
|
|
\File dirtylib.cpp
|
|
|
|
\Description
|
|
Platform specific support library for network code. Suppplies
|
|
simple time, memory, and semaphore functions.
|
|
|
|
\Copyright
|
|
Copyright (c) Electronic Arts 2002-2018. ALL RIGHTS RESERVED.
|
|
|
|
\Version 01/02/02 (eesponda) Initial C++ version ported to use EAThread
|
|
*/
|
|
/********************************************************************************H*/
|
|
|
|
#include "eathread/eathread_mutex.h"
|
|
|
|
#include "DirtySDK/platform.h"
|
|
#include "DirtySDK/dirtysock/dirtymem.h"
|
|
|
|
#include "DirtySDK/dirtysock/dirtylib.h"
|
|
|
|
/*** Type Definitions ************************************************************/
|
|
|
|
// critical section state
|
|
struct NetCritPrivT
|
|
{
|
|
EA::Thread::Mutex Mutex; //!< mutex state, must come first
|
|
|
|
uint8_t bEnabled; //!< controls if this lock is enabled
|
|
uint8_t _pad[3];
|
|
|
|
int32_t iMemGroup; //!< memory group identifier
|
|
void *pMemGroupUserdata; //!< user data passed along with allocation
|
|
};
|
|
|
|
/*** Variables *******************************************************************/
|
|
|
|
// global critical section
|
|
static NetCritPrivT _NetLib_GlobalCrit;
|
|
|
|
// sets the functions to no-op in this situation
|
|
#if defined(DIRTYCODE_LINUX)
|
|
extern uint8_t _NetLib_bSingleThreaded;
|
|
#else
|
|
static uint8_t _NetLib_bSingleThreaded = FALSE;
|
|
#endif
|
|
|
|
/*** Public Functions *************************************************************/
|
|
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function NetCritInit
|
|
|
|
\Description
|
|
Initialize a critical section for use. Allocates persistant storage
|
|
for the lifetime of the critical section if not using the global crit.
|
|
|
|
\Input *pCrit - critical section marker
|
|
\Input *pCritName - name of the critical section
|
|
|
|
\Output
|
|
int32_t - zero=success, negative=failure
|
|
|
|
\Version 09/26/2017 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t NetCritInit(NetCritT *pCrit, const char *pCritName)
|
|
{
|
|
return(NetCritInit2(pCrit, pCritName, NETCRIT_OPTION_NONE));
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function NetCritInit2
|
|
|
|
\Description
|
|
Initialize a critical section for use. Allocates persistant storage
|
|
for the lifetime of the critical section if not using the global crit.
|
|
|
|
\Input *pCrit - critical section marker
|
|
\Input *pCritName - name of the critical section
|
|
\Input uFlags - NETCRIT_OPTIONS_* flag options to set on the crit
|
|
|
|
\Output
|
|
int32_t - zero=success, negative=failure
|
|
|
|
\Version 07/24/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t NetCritInit2(NetCritT *pCrit, const char *pCritName, uint32_t uFlags)
|
|
{
|
|
NetCritPrivT *pPriv;
|
|
EA::Thread::MutexParameters Params;
|
|
ds_strnzcpy(Params.mName, pCritName, sizeof(Params.mName));
|
|
Params.mbIntraProcess = true;
|
|
|
|
// allocate memory if necessary
|
|
if (pCrit != NULL)
|
|
{
|
|
int32_t iMemGroup;
|
|
void *pMemGroupUserdata;
|
|
|
|
// query memgroup info
|
|
DirtyMemGroupQuery(&iMemGroup, &pMemGroupUserdata);
|
|
|
|
// allocate the memory needed for mutex state
|
|
if ((pCrit->pData = (NetCritPrivT *)DirtyMemAlloc(sizeof(*pCrit->pData), DIRTYTHREAD_MEMID, iMemGroup, pMemGroupUserdata)) == NULL)
|
|
{
|
|
return(-1);
|
|
}
|
|
ds_memclr(pCrit->pData, sizeof(*pCrit->pData));
|
|
pCrit->pData->iMemGroup = iMemGroup;
|
|
pCrit->pData->pMemGroupUserdata = pMemGroupUserdata;
|
|
}
|
|
/* we always clear the single-thread enable option on the global crit. it would be counter productive if it was
|
|
enabled when we are in single-threaded mode */
|
|
else
|
|
{
|
|
uFlags &= ~NETCRIT_OPTION_SINGLETHREADENABLE;
|
|
}
|
|
|
|
pPriv = (pCrit ? pCrit->pData : &_NetLib_GlobalCrit);
|
|
pPriv->Mutex.Init(&Params);
|
|
pPriv->bEnabled = !_NetLib_bSingleThreaded || ((uFlags & NETCRIT_OPTION_SINGLETHREADENABLE) == NETCRIT_OPTION_SINGLETHREADENABLE);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function NetCritKill
|
|
|
|
\Description
|
|
Release resources and destroy critical section.
|
|
|
|
\Input *pCrit - critical section marker
|
|
|
|
\Version 09/26/2017 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
void NetCritKill(NetCritT *pCrit)
|
|
{
|
|
EA::Thread::Mutex *pMutex = (pCrit ? &pCrit->pData->Mutex : &_NetLib_GlobalCrit.Mutex);
|
|
pMutex->~Mutex();
|
|
|
|
// if we are not using the global crit free the memory
|
|
if (pCrit != NULL)
|
|
{
|
|
NetCritPrivT *pPriv = pCrit->pData;
|
|
DirtyMemFree(pPriv, DIRTYTHREAD_MEMID, pPriv->iMemGroup, pPriv->pMemGroupUserdata);
|
|
pCrit->pData = NULL;
|
|
}
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function NetCritEnter
|
|
|
|
\Description
|
|
Enter a critical section, blocking if needed.
|
|
|
|
\Input *pCrit - critical section marker
|
|
|
|
\Version 09/26/2017 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
void NetCritEnter(NetCritT *pCrit)
|
|
{
|
|
NetCritPrivT *pPriv = (pCrit ? pCrit->pData : &_NetLib_GlobalCrit);
|
|
if (pPriv->bEnabled)
|
|
{
|
|
pPriv->Mutex.Lock();
|
|
}
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function NetCritTry
|
|
|
|
\Description
|
|
Attempt to gain access to critical section. Always returns immediately
|
|
regadless of access status. A thread that already has access to a critical
|
|
section can always receive repeated access to it.
|
|
|
|
\Input *pCrit - critical section marker
|
|
|
|
\Output
|
|
int32_t - zero=unable to get access, non-zero=access granted
|
|
|
|
\Version 09/26/2017 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t NetCritTry(NetCritT *pCrit)
|
|
{
|
|
NetCritPrivT *pPriv = (pCrit ? pCrit->pData : &_NetLib_GlobalCrit);
|
|
if (pPriv->bEnabled)
|
|
{
|
|
return(pPriv->Mutex.Lock(EA::Thread::kTimeoutImmediate) > 0);
|
|
}
|
|
else
|
|
{
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function NetCritLeave
|
|
|
|
\Description
|
|
Leave a critical section. Must be called once for every NetCritEnter (or
|
|
successful NetCritTry).
|
|
|
|
\Input *pCrit - critical section marker
|
|
|
|
\Version 09/26/2017 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
void NetCritLeave(NetCritT *pCrit)
|
|
{
|
|
NetCritPrivT *pPriv = (pCrit ? pCrit->pData : &_NetLib_GlobalCrit);
|
|
if (pPriv->bEnabled)
|
|
{
|
|
pPriv->Mutex.Unlock();
|
|
}
|
|
}
|
|
|