nvidia-texture-tools/src/nvthread/Thread.cpp

145 lines
2.8 KiB
C++
Raw Normal View History

2011-09-27 17:48:46 +00:00
// This code is in the public domain -- castano@gmail.com
#include "Thread.h"
#if NV_OS_WIN32
2011-09-27 18:12:32 +00:00
#include "Win32.h"
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2011-09-27 18:12:32 +00:00
#include <pthread.h>
#include <unistd.h> // usleep
2011-09-27 17:48:46 +00:00
#endif
using namespace nv;
struct Thread::Private
{
#if NV_OS_WIN32
2011-09-27 18:12:32 +00:00
HANDLE thread;
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2011-09-27 18:12:32 +00:00
pthread_t thread;
2011-09-27 17:48:46 +00:00
#endif
ThreadFunc * func;
void * arg;
};
2011-09-27 18:12:32 +00:00
2011-09-27 17:48:46 +00:00
#if NV_OS_WIN32
unsigned long __stdcall threadFunc(void * arg) {
2012-07-20 16:19:03 +00:00
Thread::Private * thread = (Thread::Private *)arg;
2011-09-27 17:48:46 +00:00
thread->func(thread->arg);
return 0;
}
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2011-09-27 18:12:32 +00:00
2011-09-27 17:48:46 +00:00
extern "C" void * threadFunc(void * arg) {
2012-07-20 16:19:03 +00:00
Thread::Private * thread = (Thread::Private *)arg;
2011-09-27 18:12:32 +00:00
thread->func(thread->arg);
pthread_exit(0);
2011-09-27 17:48:46 +00:00
}
2011-09-27 18:12:32 +00:00
2011-09-27 17:48:46 +00:00
#endif
Thread::Thread() : p(new Private)
{
p->thread = 0;
}
Thread::~Thread()
{
2011-09-27 18:12:32 +00:00
nvDebugCheck(p->thread == 0);
2011-09-27 17:48:46 +00:00
}
void Thread::start(ThreadFunc * func, void * arg)
{
2012-07-20 16:19:03 +00:00
p->func = func;
p->arg = arg;
2011-09-27 17:48:46 +00:00
#if NV_OS_WIN32
2012-07-20 16:19:03 +00:00
p->thread = CreateThread(NULL, 0, threadFunc, p.ptr(), 0, NULL);
//p->thread = (HANDLE)_beginthreadex (0, 0, threadFunc, p.ptr(), 0, NULL); // @@ So that we can call CRT functions...
2011-09-27 18:12:32 +00:00
nvDebugCheck(p->thread != NULL);
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2012-07-20 16:19:03 +00:00
int result = pthread_create(&p->thread, NULL, threadFunc, p.ptr());
2011-09-27 18:12:32 +00:00
nvDebugCheck(result == 0);
2011-09-27 17:48:46 +00:00
#endif
}
void Thread::wait()
{
#if NV_OS_WIN32
DWORD status = WaitForSingleObject (p->thread, INFINITE);
nvCheck (status == WAIT_OBJECT_0);
BOOL ok = CloseHandle (p->thread);
p->thread = NULL;
nvCheck (ok);
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2011-09-27 18:12:32 +00:00
int result = pthread_join(p->thread, NULL);
2011-09-27 17:48:46 +00:00
p->thread = 0;
2011-09-27 18:12:32 +00:00
nvDebugCheck(result == 0);
2011-09-27 17:48:46 +00:00
#endif
}
bool Thread::isRunning () const
{
#if NV_OS_WIN32
2011-09-27 18:12:32 +00:00
return p->thread != NULL;
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2011-09-27 18:12:32 +00:00
return p->thread != 0;
2011-09-27 17:48:46 +00:00
#endif
}
/*static*/ void Thread::spinWait(uint count)
{
2011-09-27 18:12:32 +00:00
for (uint i = 0; i < count; i++) {}
2011-09-27 17:48:46 +00:00
}
/*static*/ void Thread::yield()
{
#if NV_OS_WIN32
2011-09-27 18:12:32 +00:00
SwitchToThread();
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2011-09-27 18:12:32 +00:00
int result = sched_yield();
nvDebugCheck(result == 0);
2011-09-27 17:48:46 +00:00
#endif
}
/*static*/ void Thread::sleep(uint ms)
{
#if NV_OS_WIN32
2011-09-27 18:12:32 +00:00
Sleep(ms);
2013-06-07 17:53:55 +00:00
#elif NV_OS_USE_PTHREAD
2011-09-27 18:12:32 +00:00
usleep(1000 * ms);
2011-09-27 17:48:46 +00:00
#endif
}
/*static*/ void Thread::wait(Thread * threads, uint count)
{
/*#if NV_OS_WIN32
// @@ Is there any advantage in doing this?
nvDebugCheck(count < MAXIMUM_WAIT_OBJECTS);
HANDLE * handles = new HANDLE[count];
for (uint i = 0; i < count; i++) {
handles[i] = threads->p->thread;
}
DWORD result = WaitForMultipleObjects(count, handles, TRUE, INFINITE);
for (uint i = 0; i < count; i++) {
CloseHandle (threads->p->thread);
threads->p->thread = 0;
}
2011-09-27 17:48:46 +00:00
delete [] handles;
#else*/
for (uint i = 0; i < count; i++) {
threads[i].wait();
}
//#endif
2011-09-27 18:12:32 +00:00
}