tge/engine/platformX86UNIX/x86UNIXSemaphore.cc
2025-02-17 23:17:30 -06:00

94 lines
2.6 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platformX86UNIX/platformX86UNIX.h"
#include "platform/platformSemaphore.h"
#include <pthread.h>
#include <errno.h>
//
// Emulate the same behavior as the windows semaphore functions. We use
// the phread functions to accomplish this as we are using them already.
//
struct sem_private {
pthread_mutex_t mutex;
pthread_cond_t con;
int count;
};
void * Semaphore::createSemaphore(U32 initialCount)
{
sem_private *semaphore = new sem_private;
// Initialize the mutex
if (pthread_mutex_init(&(semaphore->mutex), NULL))
AssertFatal (false, "Semeaphore::createSemaphore: unable to create mutex");
// Initialize the condition
if (pthread_cond_init(&(semaphore->con), NULL))
AssertFatal (false, "Semeaphore::createSemaphore: unable to create condition");
semaphore->count = initialCount;
return (semaphore);
}
void Semaphore::destroySemaphore(void * semaphore)
{
AssertFatal (semaphore, "Semaphore::destroySemaphore: invalid semaphore.");
sem_private *sem = static_cast<sem_private *>(semaphore);
pthread_mutex_destroy(&(sem->mutex));
pthread_cond_destroy(&(sem->con));
delete sem;
}
bool Semaphore::acquireSemaphore(void * semaphore, bool block)
{
AssertFatal (semaphore, "Semaphore::acqireSemaphore: invalid semaphore.");
sem_private *sem = static_cast<sem_private *>(semaphore);
if (block)
{
int result;
pthread_mutex_lock(&(sem->mutex));
while (sem->count <= 0)
{
result = pthread_cond_wait(&(sem->con), &(sem->mutex));
if (result && errno != EINTR)
break;
}
sem->count--;
pthread_mutex_unlock(&(sem->mutex));
return (true);
}
else
{
struct timespec tm;
int result;
result = pthread_mutex_trylock(&(sem->mutex));
if (result == 0)
{
tm.tv_sec = 0;
tm.tv_nsec = 0;
while(sem->count <= 0)
{
result = pthread_cond_timedwait(&(sem->con), &(sem->mutex), &tm);
if (result && (errno != EINTR))
break;
}
sem->count--;
pthread_mutex_unlock(&(sem->mutex));
return true;
}
return false;
}
}
void Semaphore::releaseSemaphore(void * semaphore)
{
AssertFatal(semaphore, "Semaphore::releaseSemaphore: invalid semaphore.");
sem_private *sem = static_cast<sem_private *>(semaphore);
pthread_mutex_lock(&(sem->mutex));
sem->count++;
pthread_mutex_unlock(&(sem->mutex));
pthread_cond_broadcast(&(sem->con));
}