Serious-Engine/Sources/Engine/Base/Unix/UnixSynchronization.cpp
Ryan C. Gordon 24cb244d43 First attempt to hand-merge Ryan's Linux and Mac OS X port.
This was a _ton_ of changes, made 15 years ago, so there are probably some
problems to work out still.

Among others: Engine/Base/Stream.* was mostly abandoned and will need to be
re-ported.

Still, this is a pretty good start, and probably holds a world record for
lines of changes or something.  :)
2016-03-28 23:46:13 -04:00

157 lines
3.4 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "Engine/StdH.h"
#include <Engine/Base/Synchronization.h>
CTCriticalSection::CTCriticalSection(void)
{
cs_pvObject = (void *) new pthread_mutex_t;
pthread_mutex_init((pthread_mutex_t *) cs_pvObject, NULL);
LockCounter = 0;
owner = 0;
}
CTCriticalSection::~CTCriticalSection(void)
{
pthread_mutex_destroy((pthread_mutex_t *) cs_pvObject);
delete (pthread_mutex_t *) cs_pvObject;
}
INDEX CTCriticalSection::Lock(void)
{
if (owner == pthread_self())
return(++LockCounter);
pthread_mutex_lock((pthread_mutex_t *) cs_pvObject);
owner = pthread_self();
return(++LockCounter);
}
INDEX CTCriticalSection::TryToLock(void)
{
if (owner == pthread_self())
return(++LockCounter);
if (pthread_mutex_trylock((pthread_mutex_t *) cs_pvObject) == EBUSY)
return(0);
owner = pthread_self();
return(++LockCounter);
}
INDEX CTCriticalSection::Unlock(void)
{
if (owner == pthread_self())
{
if (LockCounter > 0)
{
if (--LockCounter == 0)
{
pthread_mutex_unlock((pthread_mutex_t *) cs_pvObject);
owner = 0;
}
}
}
return(LockCounter);
}
CTSingleLock::CTSingleLock(CTCriticalSection *pcs, BOOL bLock) : sl_cs(*pcs)
{
// initially not locked
sl_bLocked = FALSE;
sl_iLastLockedIndex = -2;
// critical section must have index assigned
//ASSERT(sl_cs.cs_iIndex>=1||sl_cs.cs_iIndex==-1);
// if should lock immediately
if (bLock) {
Lock();
}
}
CTSingleLock::~CTSingleLock(void)
{
// if locked
if (sl_bLocked) {
// unlock
Unlock();
}
}
void CTSingleLock::Lock(void)
{
// must not be locked
ASSERT(!sl_bLocked);
ASSERT(sl_iLastLockedIndex==-2);
// if not locked
if (!sl_bLocked) {
// lock
INDEX ctLocks = sl_cs.Lock();
// if this mutex was not locked already
// if (ctLocks==1) {
// // check that locking in given order
// if (sl_cs.cs_iIndex!=-1) {
// ASSERT(_iLastLockedMutex<sl_cs.cs_iIndex);
// sl_iLastLockedIndex = _iLastLockedMutex;
// _iLastLockedMutex = sl_cs.cs_iIndex;
// }
// }
}
sl_bLocked = TRUE;
}
BOOL CTSingleLock::TryToLock(void)
{
// must not be locked
ASSERT(!sl_bLocked);
// if not locked
if (!sl_bLocked) {
// if can lock
INDEX ctLocks = sl_cs.TryToLock();
if (ctLocks>=1) {
sl_bLocked = TRUE;
// if this mutex was not locked already
// if (ctLocks==1) {
// // check that locking in given order
// if (sl_cs.cs_iIndex!=-1) {
// ASSERT(_iLastLockedMutex<sl_cs.cs_iIndex);
// sl_iLastLockedIndex = _iLastLockedMutex;
// _iLastLockedMutex = sl_cs.cs_iIndex;
// }
// }
}
}
return sl_bLocked;
}
BOOL CTSingleLock::IsLocked(void)
{
return sl_bLocked;
}
void CTSingleLock::Unlock(void)
{
// must be locked
ASSERT(sl_bLocked);
// if locked
if (sl_bLocked) {
// unlock
INDEX ctLocks = sl_cs.Unlock();
// if unlocked completely
if (ctLocks==0) {
// check that unlocking in exact reverse order
// if (sl_cs.cs_iIndex!=-1) {
// ASSERT(_iLastLockedMutex==sl_cs.cs_iIndex);
// _iLastLockedMutex = sl_iLastLockedIndex;
// sl_iLastLockedIndex = -2;
// }
}
}
sl_bLocked = FALSE;
}