mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-24 12:35:53 +01:00
Add pthread module for threading.
This commit is contained in:
parent
4d52ea18ad
commit
920c947d55
@ -1,4 +1,4 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
|
||||||
PROJECT(TexC)
|
PROJECT(TexC)
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(BPTCEncoder)
|
ADD_SUBDIRECTORY(BPTCEncoder)
|
||||||
|
@ -34,19 +34,44 @@ INCLUDE_DIRECTORIES( ${TexC_BINARY_DIR}/IO/include )
|
|||||||
|
|
||||||
INCLUDE_DIRECTORIES( ${TexC_SOURCE_DIR}/Core/include )
|
INCLUDE_DIRECTORIES( ${TexC_SOURCE_DIR}/Core/include )
|
||||||
|
|
||||||
SET( THREAD_API "None" )
|
SET( THREAD_API "None" CACHE STRING "API used to implement threading operations")
|
||||||
|
SET( THREAD_APIS_AVAILABLE "None" )
|
||||||
|
|
||||||
FIND_PACKAGE( Boost COMPONENTS thread system )
|
FIND_PACKAGE( Boost COMPONENTS thread system )
|
||||||
IF( Boost_FOUND )
|
IF( Boost_FOUND )
|
||||||
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
|
|
||||||
|
|
||||||
|
SET( THREAD_APIS_AVAILABLE ${THREAD_APIS_AVAILABLE} "Boost" )
|
||||||
|
IF( THREAD_API MATCHES "None" )
|
||||||
SET( THREAD_API "Boost" )
|
SET( THREAD_API "Boost" )
|
||||||
SET( SOURCES ${SOURCES} "src/ThreadBoost.cpp" )
|
ENDIF()
|
||||||
|
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FIND_PACKAGE( Threads )
|
||||||
|
IF( CMAKE_USE_PTHREADS_INIT )
|
||||||
|
|
||||||
|
SET( THREAD_APIS_AVAILABLE ${THREAD_APIS_AVAILABLE} "PThread" )
|
||||||
|
IF( THREAD_API MATCHES "None" )
|
||||||
|
SET( THREAD_API "Boost" )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
SET_PROPERTY( CACHE THREAD_API PROPERTY STRINGS ${THREAD_APIS_AVAILABLE} )
|
||||||
|
|
||||||
|
IF( THREAD_API MATCHES "Boost")
|
||||||
|
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
|
||||||
|
SET( SOURCES ${SOURCES} "src/ThreadBoost.cpp" )
|
||||||
LINK_DIRECTORIES( ${Boost_LIBRARY_DIR} )
|
LINK_DIRECTORIES( ${Boost_LIBRARY_DIR} )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF( NOT THREAD_API MATCHES "None")
|
IF( THREAD_API MATCHES "PThread" )
|
||||||
|
SET( SOURCES ${SOURCES} "src/ThreadPThread.cpp" )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF( THREAD_API MATCHES "None")
|
||||||
|
MESSAGE( FATAL_ERROR "Could not find suitable threading library." )
|
||||||
|
ELSE()
|
||||||
SET( SOURCES ${SOURCES} "src/Thread.cpp" )
|
SET( SOURCES ${SOURCES} "src/Thread.cpp" )
|
||||||
SET( SOURCES ${SOURCES} "src/ThreadGroup.cpp" )
|
SET( SOURCES ${SOURCES} "src/ThreadGroup.cpp" )
|
||||||
SET( SOURCES ${SOURCES} "src/WorkerQueue.cpp" )
|
SET( SOURCES ${SOURCES} "src/WorkerQueue.cpp" )
|
||||||
@ -54,8 +79,6 @@ IF( NOT THREAD_API MATCHES "None")
|
|||||||
SET( HEADERS ${HEADERS} "src/Thread.h" )
|
SET( HEADERS ${HEADERS} "src/Thread.h" )
|
||||||
SET( HEADERS ${HEADERS} "src/ThreadGroup.h" )
|
SET( HEADERS ${HEADERS} "src/ThreadGroup.h" )
|
||||||
SET( HEADERS ${HEADERS} "src/WorkerQueue.h" )
|
SET( HEADERS ${HEADERS} "src/WorkerQueue.h" )
|
||||||
ELSE()
|
|
||||||
MESSAGE( FATAL_ERROR "Could not find suitable threading library." )
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
ADD_LIBRARY( TexCompCore
|
ADD_LIBRARY( TexCompCore
|
||||||
@ -66,10 +89,14 @@ ADD_LIBRARY( TexCompCore
|
|||||||
TARGET_LINK_LIBRARIES( TexCompCore TexCompIO )
|
TARGET_LINK_LIBRARIES( TexCompCore TexCompIO )
|
||||||
TARGET_LINK_LIBRARIES( TexCompCore BPTCEncoder )
|
TARGET_LINK_LIBRARIES( TexCompCore BPTCEncoder )
|
||||||
|
|
||||||
IF( Boost_FOUND )
|
IF( THREAD_API MATCHES "Boost" )
|
||||||
TARGET_LINK_LIBRARIES( TexCompCore ${Boost_LIBRARIES} )
|
TARGET_LINK_LIBRARIES( TexCompCore ${Boost_LIBRARIES} )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF( THREAD_API MATCHES "PThread" )
|
||||||
|
TARGET_LINK_LIBRARIES( TexCompCore ${CMAKE_THREAD_LIBS_INIT} )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF( NOT WIN32 AND NOT APPLE )
|
IF( NOT WIN32 AND NOT APPLE )
|
||||||
TARGET_LINK_LIBRARIES( TexCompCore rt )
|
TARGET_LINK_LIBRARIES( TexCompCore rt )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
249
Core/src/ThreadPThread.cpp
Normal file
249
Core/src/ThreadPThread.cpp
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#include "Thread.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static void ReportErrorAndExit(int err, const char *msg) {
|
||||||
|
char errMsg[1024];
|
||||||
|
sprintf(errMsg, "Thread error -- %s: ", msg);
|
||||||
|
|
||||||
|
errno = err;
|
||||||
|
perror(errMsg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Thread Implementation
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class TCThreadImpl : public TCThreadBaseImpl {
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void *RunThread(void *arg) {
|
||||||
|
TCThreadImpl *impl = (TCThreadImpl *)arg;
|
||||||
|
|
||||||
|
impl->m_Callable();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t m_ThreadID;
|
||||||
|
TCCallable &m_Callable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TCThreadImpl(TCCallable &callable) :
|
||||||
|
m_Callable(callable)
|
||||||
|
{
|
||||||
|
int result = pthread_create(&m_ThreadID, NULL, RunThread, (void *)this);
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_create");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual ~TCThreadImpl() { }
|
||||||
|
|
||||||
|
void Join() {
|
||||||
|
void *status;
|
||||||
|
int result = pthread_join(m_ThreadID, &status);
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_join");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TCThreadImplFactory : public TCThreadBaseImplFactory {
|
||||||
|
TCCallable &m_Callable;
|
||||||
|
public:
|
||||||
|
TCThreadImplFactory(TCCallable &callable) : m_Callable(callable) { }
|
||||||
|
virtual ~TCThreadImplFactory() { }
|
||||||
|
virtual TCThreadBaseImpl *CreateImpl() const {
|
||||||
|
return new TCThreadImpl(m_Callable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TCThread::TCThread(TCCallable &callable)
|
||||||
|
: TCThreadBase(TCThreadImplFactory(callable))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void TCThread::Join() {
|
||||||
|
CheckReferenceCount();
|
||||||
|
((TCThreadImpl *)m_Impl)->Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCThread::Yield() {
|
||||||
|
int result = pthread_yield();
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_yield");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Mutex Implementation
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class TCMutexImpl : public TCThreadBaseImpl {
|
||||||
|
private:
|
||||||
|
pthread_mutex_t m_Mutex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
pthread_mutex_t *GetMutex() { return &m_Mutex; }
|
||||||
|
TCMutexImpl() : TCThreadBaseImpl() {
|
||||||
|
int result = pthread_mutex_init( &m_Mutex, NULL );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_mutex_init");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~TCMutexImpl() {
|
||||||
|
int result = pthread_mutex_destroy( &m_Mutex );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_mutex_destroy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class TCMutexImplFactory : public TCThreadBaseImplFactory {
|
||||||
|
public:
|
||||||
|
TCMutexImplFactory() { }
|
||||||
|
virtual ~TCMutexImplFactory() { }
|
||||||
|
virtual TCThreadBaseImpl *CreateImpl() const {
|
||||||
|
return new TCMutexImpl();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TCMutex::TCMutex() : TCThreadBase(TCMutexImplFactory())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Lock Implementation
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class TCLockImpl : public TCThreadBaseImpl {
|
||||||
|
private:
|
||||||
|
pthread_mutex_t *const m_MutexPtr;
|
||||||
|
public:
|
||||||
|
TCLockImpl(TCMutex &mutex)
|
||||||
|
: m_MutexPtr(((TCMutexImpl *)(mutex.m_Impl))->GetMutex())
|
||||||
|
{
|
||||||
|
int result = pthread_mutex_lock( m_MutexPtr );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_mutex_lock");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~TCLockImpl() {
|
||||||
|
int result = pthread_mutex_unlock( m_MutexPtr );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_mutex_unlock");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_t *GetMutexPtr() const { return m_MutexPtr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class TCLockImplFactory : public TCThreadBaseImplFactory {
|
||||||
|
private:
|
||||||
|
TCMutex &m_Mutex;
|
||||||
|
public:
|
||||||
|
TCLockImplFactory(TCMutex &mutex) : m_Mutex(mutex){ }
|
||||||
|
virtual ~TCLockImplFactory() { }
|
||||||
|
virtual TCThreadBaseImpl *CreateImpl() const {
|
||||||
|
return new TCLockImpl(m_Mutex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TCLock::TCLock(TCMutex &mutex) : TCThreadBase(TCLockImplFactory(mutex))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Condition Variable Implementation
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class TCConditionVariableImpl : public TCThreadBaseImpl {
|
||||||
|
private:
|
||||||
|
pthread_cond_t m_CV;
|
||||||
|
public:
|
||||||
|
TCConditionVariableImpl() {
|
||||||
|
int result = pthread_cond_init( &m_CV, NULL );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_cond_init");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~TCConditionVariableImpl() {
|
||||||
|
int result = pthread_cond_destroy( &m_CV );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit(result, "pthread_cond_destroy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wait(TCLock &lock) {
|
||||||
|
TCLockImpl *lockImpl = (TCLockImpl *)(lock.m_Impl);
|
||||||
|
|
||||||
|
int result = pthread_cond_wait( &m_CV, lockImpl->GetMutexPtr() );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit( result, "pthread_cond_wait" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyOne() {
|
||||||
|
int result = pthread_cond_signal( &m_CV );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit( result, "pthread_cond_signal" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyAll() {
|
||||||
|
int result = pthread_cond_broadcast( &m_CV );
|
||||||
|
if(result != 0) {
|
||||||
|
ReportErrorAndExit( result, "pthread_cond_broadcast" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TCConditionVariableImplFactory : public TCThreadBaseImplFactory {
|
||||||
|
public:
|
||||||
|
TCConditionVariableImplFactory() { }
|
||||||
|
virtual ~TCConditionVariableImplFactory() { }
|
||||||
|
virtual TCThreadBaseImpl *CreateImpl() const {
|
||||||
|
return new TCConditionVariableImpl();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TCConditionVariable::TCConditionVariable()
|
||||||
|
: TCThreadBase(TCConditionVariableImplFactory())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void TCConditionVariable::Wait(TCLock &lock) {
|
||||||
|
CheckReferenceCount();
|
||||||
|
|
||||||
|
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
|
||||||
|
impl->Wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCConditionVariable::NotifyOne() {
|
||||||
|
CheckReferenceCount();
|
||||||
|
|
||||||
|
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
|
||||||
|
impl->NotifyOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCConditionVariable::NotifyAll() {
|
||||||
|
CheckReferenceCount();
|
||||||
|
|
||||||
|
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
|
||||||
|
impl->NotifyAll();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user