dolphin/Source/Core/Common/Src/StdThread.h
Rodolfo Osvaldo Bogado c569b33829 First Revert my changes to VertexLoader.cpp, i don't own the games that get error so i revert the changes until i can test it myself.
Second:
A experiment. implemented parallelization in texture decoding using openmp. is most a experiment to test the performance in different os/plataforms. in my system (windows x64 amd 1055t) give a speedup in large textures, but i tested in in intel dual core and gives a slowdown. o i limited the use for large textures and cpus with more than 3 cores.
please test an let me know if it improves or degrades the speed.
please for linux and osx user. to enable this you will have to enable your compiler support for openmp to test this code.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7284 8ced0084-cf51-0410-be5f-012b33b47a6e
2011-03-04 22:48:54 +00:00

308 lines
5.0 KiB
Objective-C

#ifndef STD_THREAD_H_
#define STD_THREAD_H_
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
// GCC 4.4 provides <thread>
#include <thread>
#else
// partial std::thread implementation for win32/pthread
#include <algorithm>
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
#define USE_RVALUE_REFERENCES
#endif
#ifdef __APPLE__
#import <Foundation/NSAutoreleasePool.h>
#endif
#if defined(_WIN32)
// WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#if defined(_MSC_VER) && defined(_MT)
// When linking with LIBCMT (the multithreaded C library), Microsoft recommends
// using _beginthreadex instead of CreateThread.
#define USE_BEGINTHREADEX
#include <process.h>
#endif
#ifdef USE_BEGINTHREADEX
#define THREAD_ID unsigned
#define THREAD_RETURN unsigned __stdcall
#else
#define THREAD_ID DWORD
#define THREAD_RETURN DWORD WINAPI
#endif
#define THREAD_HANDLE HANDLE
#else
// PTHREAD
#include <unistd.h>
#ifndef _POSIX_THREADS
#error unsupported platform (no pthreads?)
#endif
#include <pthread.h>
#define THREAD_ID pthread_t
#define THREAD_HANDLE pthread_t
#define THREAD_RETURN void*
#endif
namespace std
{
class thread
{
public:
typedef THREAD_HANDLE native_handle_type;
class id
{
friend class thread;
public:
id() : m_thread(0) {}
id(THREAD_ID _id) : m_thread(_id) {}
bool operator==(const id& rhs) const
{
return m_thread == rhs.m_thread;
}
bool operator!=(const id& rhs) const
{
return !(*this == rhs);
}
bool operator<(const id& rhs) const
{
return m_thread < rhs.m_thread;
}
private:
THREAD_ID m_thread;
};
// no variadic template support in msvc
//template <typename C, typename... A>
//thread(C&& func, A&&... args);
template <typename C>
thread(C func)
{
StartThread(new Func<C>(func));
}
template <typename C, typename A>
thread(C func, A arg)
{
StartThread(new FuncArg<C, A>(func, arg));
}
thread() /*= default;*/ {}
#ifdef USE_RVALUE_REFERENCES
thread(const thread&) /*= delete*/;
thread(thread&& other)
{
#else
thread(const thread& t)
{
// ugly const_cast to get around lack of rvalue references
thread& other = const_cast<thread&>(t);
#endif
swap(other);
}
#ifdef USE_RVALUE_REFERENCES
thread& operator=(const thread&) /*= delete*/;
thread& operator=(thread&& other)
{
#else
thread& operator=(const thread& t)
{
// ugly const_cast to get around lack of rvalue references
thread& other = const_cast<thread&>(t);
#endif
if (joinable())
detach();
swap(other);
return *this;
}
~thread()
{
if (joinable())
detach();
}
bool joinable() const
{
return m_id != id();
}
id get_id() const
{
return m_id;
}
native_handle_type native_handle()
{
#ifdef _WIN32
return m_handle;
#else
return m_id.m_thread;
#endif
}
void join()
{
#ifdef _WIN32
WaitForSingleObject(m_handle, INFINITE);
detach();
#else
pthread_join(m_id.m_thread, NULL);
m_id = id();
#endif
}
void detach()
{
#ifdef _WIN32
CloseHandle(m_handle);
#else
pthread_detach(m_id.m_thread);
#endif
m_id = id();
}
void swap(thread& other)
{
std::swap(m_id, other.m_id);
#ifdef _WIN32
std::swap(m_handle, other.m_handle);
#endif
}
static unsigned hardware_concurrency()
{
#ifdef _WIN32
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
#else
return 0;
#endif
}
private:
id m_id;
#ifdef _WIN32
native_handle_type m_handle;
#endif
template <typename F>
void StartThread(F* param)
{
#ifdef USE_BEGINTHREADEX
m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
#elif defined(_WIN32)
m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
#else
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024 * 1024);
if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param))
m_id = id();
#endif
}
template <typename C>
class Func
{
public:
Func(C _func) : func(_func) {}
void Run() { func(); }
private:
C const func;
};
template <typename C, typename A>
class FuncArg
{
public:
FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
void Run() { func(arg); }
private:
C const func;
A arg;
};
template <typename F>
static THREAD_RETURN RunAndDelete(void* param)
{
#ifdef __APPLE__
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#endif
static_cast<F*>(param)->Run();
delete static_cast<F*>(param);
#ifdef __APPLE__
[pool release];
#endif
return 0;
}
};
namespace this_thread
{
inline void yield()
{
#ifdef _WIN32
Sleep(0);
#else
sleep(0);
#endif
}
inline thread::id get_id()
{
#ifdef _WIN32
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}
} // namespace this_thread
} // namespace std
#undef USE_RVALUE_REFERENCES
#undef USE_BEGINTHREADEX
#undef THREAD_ID
#undef THREAD_RETURN
#undef THREAD_HANDLE
#endif
#endif