mirror of
				https://github.com/dolphin-emu/dolphin.git
				synced 2025-10-25 01:19:19 +00:00 
			
		
		
		
	git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7333 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			308 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
			
		
		
	
	
			308 lines
		
	
	
	
		
			5 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>
 | |
| #define _GLIBCXX_USE_SCHED_YIELD
 | |
| #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
 |