forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
458
Kha/Backends/Kinc-hxcpp/khacpp/include/hx/Thread.h
Normal file
458
Kha/Backends/Kinc-hxcpp/khacpp/include/hx/Thread.h
Normal file
@ -0,0 +1,458 @@
|
||||
#ifdef HX_THREAD_H_OVERRIDE
|
||||
// Users can define their own header to use here, but there is no API
|
||||
// compatibility gaurantee for future changes.
|
||||
#include HX_THREAD_H_OVERRIDE
|
||||
#else
|
||||
|
||||
#ifndef HX_THREAD_H
|
||||
#define HX_THREAD_H
|
||||
|
||||
#ifndef HXCPP_HEADER_VERSION
|
||||
#include "hx/HeaderVersion.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE)
|
||||
|
||||
#include <kinc/threads/atomic.h>
|
||||
#include <kinc/threads/event.h>
|
||||
#include <kinc/threads/mutex.h>
|
||||
#include <kinc/threads/thread.h>
|
||||
|
||||
#elif defined(HX_WINRT)
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <mutex>
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#ifdef HXCPP_WINXP_COMPAT
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#else
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#define HXCPP_PTHREADS
|
||||
#endif
|
||||
|
||||
#ifdef RegisterClass
|
||||
#undef RegisterClass
|
||||
#endif
|
||||
|
||||
#if defined(KORE)
|
||||
|
||||
struct HxMutex {
|
||||
HxMutex() {
|
||||
kinc_mutex_init(&mutex);
|
||||
}
|
||||
|
||||
~HxMutex() {
|
||||
kinc_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
void Lock() {
|
||||
kinc_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
kinc_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
bool TryLock() {
|
||||
return kinc_mutex_try_to_lock(&mutex);
|
||||
}
|
||||
|
||||
void Clean() {
|
||||
kinc_mutex_destroy(&mutex);
|
||||
}
|
||||
private:
|
||||
kinc_mutex_t mutex;
|
||||
};
|
||||
|
||||
#define THREAD_FUNC_TYPE void
|
||||
#define THREAD_FUNC_RET return;
|
||||
|
||||
inline bool HxCreateDetachedThread(void (*func)(void *), void *param)
|
||||
{
|
||||
kinc_thread_t thread;
|
||||
kinc_thread_init(&thread, func, param);
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined(HX_WINDOWS)
|
||||
|
||||
|
||||
struct HxMutex
|
||||
{
|
||||
HxMutex()
|
||||
{
|
||||
mValid = true;
|
||||
#ifdef HX_WINRT
|
||||
InitializeCriticalSectionEx(&mCritSec,4000,0);
|
||||
#else
|
||||
InitializeCriticalSection(&mCritSec);
|
||||
#endif
|
||||
}
|
||||
~HxMutex() { if (mValid) DeleteCriticalSection(&mCritSec); }
|
||||
void Lock() { EnterCriticalSection(&mCritSec); }
|
||||
void Unlock() { LeaveCriticalSection(&mCritSec); }
|
||||
bool TryLock() { return TryEnterCriticalSection(&mCritSec); }
|
||||
bool IsValid() { return mValid; }
|
||||
void Clean()
|
||||
{
|
||||
if (mValid)
|
||||
{
|
||||
DeleteCriticalSection(&mCritSec);
|
||||
mValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool mValid;
|
||||
CRITICAL_SECTION mCritSec;
|
||||
};
|
||||
|
||||
|
||||
#define THREAD_FUNC_TYPE DWORD WINAPI
|
||||
#define THREAD_FUNC_RET return 0;
|
||||
|
||||
inline bool HxCreateDetachedThread(DWORD (WINAPI *func)(void *), void *param)
|
||||
{
|
||||
return (CreateThread(NULL, 0, func, param, 0, 0) != 0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct HxMutex
|
||||
{
|
||||
HxMutex()
|
||||
{
|
||||
pthread_mutexattr_t mta;
|
||||
pthread_mutexattr_init(&mta);
|
||||
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
|
||||
mValid = pthread_mutex_init(&mMutex,&mta) ==0;
|
||||
}
|
||||
~HxMutex() { if (mValid) pthread_mutex_destroy(&mMutex); }
|
||||
void Lock() { pthread_mutex_lock(&mMutex); }
|
||||
void Unlock() { pthread_mutex_unlock(&mMutex); }
|
||||
bool TryLock() { return !pthread_mutex_trylock(&mMutex); }
|
||||
bool IsValid() { return mValid; }
|
||||
void Clean()
|
||||
{
|
||||
if (mValid)
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
mValid = 0;
|
||||
}
|
||||
|
||||
bool mValid;
|
||||
pthread_mutex_t mMutex;
|
||||
};
|
||||
|
||||
#define THREAD_FUNC_TYPE void *
|
||||
#define THREAD_FUNC_RET return 0;
|
||||
|
||||
inline bool HxCreateDetachedThread(void *(*func)(void *), void *param)
|
||||
{
|
||||
pthread_t t;
|
||||
pthread_attr_t attr;
|
||||
if (pthread_attr_init(&attr) != 0)
|
||||
return false;
|
||||
#ifdef PTHREAD_CREATE_DETACHED
|
||||
if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
|
||||
return false;
|
||||
#endif
|
||||
if (pthread_create(&t, &attr, func, param) != 0 )
|
||||
return false;
|
||||
if (pthread_attr_destroy(&attr) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename LOCKABLE>
|
||||
struct TAutoLock
|
||||
{
|
||||
TAutoLock(LOCKABLE &inMutex) : mMutex(inMutex) { mMutex.Lock(); }
|
||||
~TAutoLock() { mMutex.Unlock(); }
|
||||
void Lock() { mMutex.Lock(); }
|
||||
void Unlock() { mMutex.Unlock(); }
|
||||
|
||||
LOCKABLE &mMutex;
|
||||
};
|
||||
|
||||
typedef TAutoLock<HxMutex> AutoLock;
|
||||
|
||||
#if defined(KORE)
|
||||
|
||||
struct HxSemaphore {
|
||||
HxSemaphore() {
|
||||
kinc_event_init(&event, true);
|
||||
}
|
||||
|
||||
~HxSemaphore() {
|
||||
kinc_event_destroy(&event);
|
||||
}
|
||||
|
||||
void Set() {
|
||||
kinc_event_signal(&event);
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
kinc_event_wait(&event);
|
||||
}
|
||||
|
||||
bool WaitSeconds(double inSeconds) {
|
||||
return kinc_event_try_to_wait(&event, inSeconds);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
kinc_event_reset(&event);
|
||||
}
|
||||
|
||||
void Clean() {
|
||||
kinc_event_destroy(&event);
|
||||
}
|
||||
private:
|
||||
kinc_event_t event;
|
||||
};
|
||||
|
||||
struct ThreadPoolSignal {
|
||||
ThreadPoolSignal() {
|
||||
kinc_event_init(&event, true);
|
||||
}
|
||||
|
||||
~ThreadPoolSignal() {
|
||||
|
||||
}
|
||||
|
||||
void Set() {
|
||||
kinc_event_signal(&event);
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
kinc_event_wait(&event);
|
||||
}
|
||||
|
||||
bool WaitSeconds(double inSeconds) {
|
||||
return kinc_event_try_to_wait(&event, inSeconds);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
kinc_event_reset(&event);
|
||||
}
|
||||
|
||||
void Clean() {
|
||||
kinc_event_destroy(&event);
|
||||
}
|
||||
private:
|
||||
kinc_event_t event;
|
||||
};
|
||||
|
||||
#elif defined(HX_WINDOWS)
|
||||
|
||||
struct HxSemaphore
|
||||
{
|
||||
HxSemaphore()
|
||||
{
|
||||
#ifdef HX_WINRT
|
||||
mSemaphore = CreateEventEx(nullptr,nullptr,0,EVENT_ALL_ACCESS);
|
||||
#else
|
||||
mSemaphore = CreateEvent(0,0,0,0);
|
||||
#endif
|
||||
}
|
||||
~HxSemaphore() { if (mSemaphore) CloseHandle(mSemaphore); }
|
||||
void Set() { SetEvent(mSemaphore); }
|
||||
void Wait()
|
||||
{
|
||||
#ifdef HX_WINRT
|
||||
WaitForSingleObjectEx(mSemaphore,INFINITE,false);
|
||||
#else
|
||||
WaitForSingleObject(mSemaphore,INFINITE);
|
||||
#endif
|
||||
}
|
||||
// Returns true on success, false on timeout
|
||||
bool WaitSeconds(double inSeconds)
|
||||
{
|
||||
#ifdef HX_WINRT
|
||||
return WaitForSingleObjectEx(mSemaphore,inSeconds*1000.0,false) != WAIT_TIMEOUT;
|
||||
#else
|
||||
return WaitForSingleObject(mSemaphore,inSeconds*1000.0) != WAIT_TIMEOUT;
|
||||
#endif
|
||||
}
|
||||
void Reset() { ResetEvent(mSemaphore); }
|
||||
void Clean() { if (mSemaphore) CloseHandle(mSemaphore); mSemaphore = 0; }
|
||||
|
||||
HANDLE mSemaphore;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#define HX_THREAD_SEMAPHORE_LOCKABLE
|
||||
|
||||
struct HxSemaphore
|
||||
{
|
||||
HxSemaphore()
|
||||
{
|
||||
mSet = false;
|
||||
mValid = true;
|
||||
pthread_cond_init(&mCondition,0);
|
||||
}
|
||||
~HxSemaphore()
|
||||
{
|
||||
if (mValid)
|
||||
{
|
||||
pthread_cond_destroy(&mCondition);
|
||||
}
|
||||
}
|
||||
// For autolock
|
||||
inline operator HxMutex &() { return mMutex; }
|
||||
void Set()
|
||||
{
|
||||
AutoLock lock(mMutex);
|
||||
if (!mSet)
|
||||
{
|
||||
mSet = true;
|
||||
pthread_cond_signal( &mCondition );
|
||||
}
|
||||
}
|
||||
void QSet()
|
||||
{
|
||||
mSet = true;
|
||||
pthread_cond_signal( &mCondition );
|
||||
}
|
||||
void Reset()
|
||||
{
|
||||
AutoLock lock(mMutex);
|
||||
mSet = false;
|
||||
}
|
||||
void QReset() { mSet = false; }
|
||||
void Wait()
|
||||
{
|
||||
AutoLock lock(mMutex);
|
||||
while( !mSet )
|
||||
pthread_cond_wait( &mCondition, &mMutex.mMutex );
|
||||
mSet = false;
|
||||
}
|
||||
// when we already hold the mMutex lock ...
|
||||
void QWait()
|
||||
{
|
||||
while( !mSet )
|
||||
pthread_cond_wait( &mCondition, &mMutex.mMutex );
|
||||
mSet = false;
|
||||
}
|
||||
// Returns true if the wait was success, false on timeout.
|
||||
bool WaitSeconds(double inSeconds)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
|
||||
int isec = (int)inSeconds;
|
||||
int usec = (int)((inSeconds-isec)*1000000.0);
|
||||
timespec spec;
|
||||
spec.tv_nsec = (tv.tv_usec + usec) * 1000;
|
||||
if (spec.tv_nsec>1000000000)
|
||||
{
|
||||
spec.tv_nsec-=1000000000;
|
||||
isec++;
|
||||
}
|
||||
spec.tv_sec = tv.tv_sec + isec;
|
||||
|
||||
AutoLock lock(mMutex);
|
||||
|
||||
int result = 0;
|
||||
// Wait for set to be true...
|
||||
while( !mSet && (result=pthread_cond_timedwait( &mCondition, &mMutex.mMutex, &spec )) != ETIMEDOUT)
|
||||
{
|
||||
if (result!=0)
|
||||
{
|
||||
// Error - something's gone wrong...
|
||||
/*
|
||||
if (result==EINVAL)
|
||||
printf("ERROR: Condition EINVAL\n");
|
||||
else if (result==EPERM)
|
||||
printf("ERROR: Condition EPERM\n");
|
||||
else
|
||||
printf("ERROR: Condition unknown error\n");
|
||||
*/
|
||||
break;
|
||||
}
|
||||
// Condition signalled - but try mSet again ...
|
||||
}
|
||||
|
||||
bool wasSet = mSet;
|
||||
mSet = false;
|
||||
return wasSet;
|
||||
}
|
||||
void Clean()
|
||||
{
|
||||
mMutex.Clean();
|
||||
if (mValid)
|
||||
{
|
||||
mValid = false;
|
||||
pthread_cond_destroy(&mCondition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HxMutex mMutex;
|
||||
pthread_cond_t mCondition;
|
||||
bool mSet;
|
||||
bool mValid;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(KORE)
|
||||
|
||||
#include <kinc/threads/thread.h>
|
||||
|
||||
inline void HxSleep(unsigned int ms)
|
||||
{
|
||||
kinc_thread_sleep(ms);
|
||||
}
|
||||
|
||||
#elif defined HX_WINRT
|
||||
|
||||
inline void HxSleep(unsigned int ms)
|
||||
{
|
||||
::Sleep(ms);
|
||||
}
|
||||
|
||||
#elif defined HX_WINDOWS
|
||||
|
||||
inline void HxSleep(unsigned int ms)
|
||||
{
|
||||
::Sleep(ms);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void HxSleep(unsigned int ms)
|
||||
{
|
||||
struct timespec t;
|
||||
struct timespec tmp;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = ms * 1000000;
|
||||
nanosleep(&t, &tmp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
Reference in New Issue
Block a user