| 
									
										
										
										
											2009-07-28 21:32:10 +00:00
										 |  |  | // Copyright (C) 2003 Dolphin Project.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-28 08:57:34 +00:00
										 |  |  | #ifndef _THREAD_H_
 | 
					
						
							|  |  |  | #define _THREAD_H_
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-27 20:47:58 +00:00
										 |  |  | #include "StdThread.h"
 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | #include "StdMutex.h"
 | 
					
						
							|  |  |  | #include "StdConditionVariable.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:58 +00:00
										 |  |  | // Don't include common.h here as it will break LogManager
 | 
					
						
							|  |  |  | #include "CommonTypes.h"
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 04:54:00 +00:00
										 |  |  | // This may not be defined outside _WIN32
 | 
					
						
							|  |  |  | #ifndef _WIN32
 | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | #ifndef INFINITE
 | 
					
						
							|  |  |  | #define INFINITE 0xffffffff
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-01-09 19:06:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-27 20:47:58 +00:00
										 |  |  | #include <xmmintrin.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-22 02:42:53 +00:00
										 |  |  | //for gettimeofday and struct time(spec|val)
 | 
					
						
							| 
									
										
										
										
											2010-01-09 19:06:23 +00:00
										 |  |  | #include <time.h>
 | 
					
						
							| 
									
										
										
										
											2010-11-20 03:24:51 +00:00
										 |  |  | #include <sys/time.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-02-24 04:54:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | namespace Common | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-27 20:47:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int CurrentThreadId(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); | 
					
						
							|  |  |  | void SetCurrentThreadAffinity(u32 mask); | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | class Event | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-03-05 22:17:28 +00:00
										 |  |  | 	Event() | 
					
						
							|  |  |  | 		: is_set(false) | 
					
						
							|  |  |  | 	{}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 	void Set() | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-03-06 00:52:04 +00:00
										 |  |  | 		std::lock_guard<std::mutex> lk(m_mutex); | 
					
						
							| 
									
										
										
										
											2011-03-05 22:17:28 +00:00
										 |  |  | 		if (!is_set) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			is_set = true; | 
					
						
							|  |  |  | 			m_condvar.notify_one(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 	void Wait() | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 		std::unique_lock<std::mutex> lk(m_mutex); | 
					
						
							| 
									
										
										
										
											2011-03-05 22:17:28 +00:00
										 |  |  | 		if (!is_set) | 
					
						
							| 
									
										
										
										
											2011-03-06 00:52:04 +00:00
										 |  |  | 			m_condvar.wait(lk, IsSet(this)); | 
					
						
							| 
									
										
										
										
											2011-03-05 22:17:28 +00:00
										 |  |  | 		is_set = false; | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2011-03-06 00:52:04 +00:00
										 |  |  | 	class IsSet | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		IsSet(const Event* ev) | 
					
						
							|  |  |  | 			: m_event(ev) | 
					
						
							|  |  |  | 		{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bool operator()() | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return m_event->is_set; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		const Event* const m_event; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	volatile bool is_set; | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 	std::condition_variable m_condvar; | 
					
						
							|  |  |  | 	std::mutex m_mutex; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TODO: doesn't work on windows with (count > 2)
 | 
					
						
							|  |  |  | class Barrier | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	Barrier(size_t count) | 
					
						
							|  |  |  | 		: m_count(count), m_waiting(0) | 
					
						
							|  |  |  | 	{} | 
					
						
							| 
									
										
										
										
											2010-06-16 14:22:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 	// block until "count" threads call Wait()
 | 
					
						
							|  |  |  | 	bool Wait() | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 		std::unique_lock<std::mutex> lk(m_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-06 00:52:04 +00:00
										 |  |  | 		// TODO: broken when next round of Wait()s
 | 
					
						
							|  |  |  | 		// is entered before all waiting threads return from the notify_all
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-05 22:17:28 +00:00
										 |  |  | 		if (m_count == ++m_waiting) | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			m_waiting = 0; | 
					
						
							|  |  |  | 			m_condvar.notify_all(); | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-03-06 00:52:04 +00:00
										 |  |  | 			m_condvar.wait(lk, IsDoneWating(this)); | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2011-03-06 00:52:04 +00:00
										 |  |  | 	class IsDoneWating | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		IsDoneWating(const Barrier* bar) | 
					
						
							|  |  |  | 			: m_bar(bar) | 
					
						
							|  |  |  | 		{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bool operator()() | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return (0 == m_bar->m_waiting); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		const Barrier* const m_bar; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | 	std::condition_variable m_condvar; | 
					
						
							|  |  |  | 	std::mutex m_mutex; | 
					
						
							|  |  |  | 	const size_t m_count; | 
					
						
							|  |  |  | 	volatile size_t m_waiting; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | void SleepCurrentThread(int ms); | 
					
						
							|  |  |  | void SwitchCurrentThread();	// On Linux, this is equal to sleep 1ms
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Use this function during a spin-wait to make the current thread
 | 
					
						
							|  |  |  | // relax while another thread is working. This may be more efficient
 | 
					
						
							|  |  |  | // than using events because event functions use kernel calls.
 | 
					
						
							|  |  |  | inline void YieldCPU() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::this_thread::yield(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-03-05 06:11:26 +00:00
										 |  |  | void SetCurrentThreadName(const char *name); | 
					
						
							| 
									
										
										
										
											2010-04-29 13:46:20 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-03-28 08:57:34 +00:00
										 |  |  | } // namespace Common
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 21:16:52 +00:00
										 |  |  | #endif // _THREAD_H_
 |