forked from dolphin-emu/dolphin
		
	git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7313 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			154 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
 | 
						|
#ifndef CONDITION_VARIABLE_H_
 | 
						|
#define CONDITION_VARIABLE_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 <condition_variable>
 | 
						|
#include <condition_variable>
 | 
						|
#else
 | 
						|
 | 
						|
// partial std::condition_variable implementation for win32/pthread
 | 
						|
 | 
						|
#include "StdMutex.h"
 | 
						|
 | 
						|
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
 | 
						|
#define USE_RVALUE_REFERENCES
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined(_WIN32) && defined(_M_X64)
 | 
						|
#define USE_CONDITION_VARIABLES
 | 
						|
#elif defined(_WIN32)
 | 
						|
#define USE_EVENTS
 | 
						|
#endif
 | 
						|
 | 
						|
namespace std
 | 
						|
{
 | 
						|
 | 
						|
class condition_variable
 | 
						|
{
 | 
						|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
						|
	typedef CONDITION_VARIABLE native_type;
 | 
						|
#elif defined(_WIN32)
 | 
						|
	typedef HANDLE native_type;
 | 
						|
#else
 | 
						|
	typedef pthread_cond_t native_type;
 | 
						|
#endif
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
#ifdef USE_EVENTS
 | 
						|
	typedef native_type native_handle_type;
 | 
						|
#else
 | 
						|
	typedef native_type* native_handle_type;
 | 
						|
#endif
 | 
						|
 | 
						|
	condition_variable()
 | 
						|
	{
 | 
						|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
						|
		InitializeConditionVariable(&m_handle);
 | 
						|
#elif defined(_WIN32)
 | 
						|
		m_handle = CreateEvent(NULL, false, false, NULL);
 | 
						|
#else
 | 
						|
		pthread_cond_init(&m_handle, NULL);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
	~condition_variable()
 | 
						|
	{
 | 
						|
#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
 | 
						|
		CloseHandle(m_handle);
 | 
						|
#elif !defined(_WIN32)
 | 
						|
		pthread_cond_destroy(&m_handle);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
	condition_variable(const condition_variable&) /*= delete*/;
 | 
						|
	condition_variable& operator=(const condition_variable&) /*= delete*/;
 | 
						|
 | 
						|
	void notify_one()
 | 
						|
	{
 | 
						|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
						|
		WakeConditionVariable(&m_handle);
 | 
						|
#elif defined(_WIN32)
 | 
						|
		SetEvent(m_handle);
 | 
						|
#else
 | 
						|
		pthread_cond_signal(&m_handle);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
	void notify_all()
 | 
						|
	{
 | 
						|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
						|
		WakeAllConditionVariable(&m_handle);
 | 
						|
#elif defined(_WIN32)
 | 
						|
		// TODO: broken
 | 
						|
		SetEvent(m_handle);
 | 
						|
#else
 | 
						|
		pthread_cond_broadcast(&m_handle);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
	void wait(unique_lock<mutex>& lock)
 | 
						|
	{
 | 
						|
#ifdef _WIN32
 | 
						|
	#ifdef USE_SRWLOCKS
 | 
						|
		SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
 | 
						|
	#elif defined(USE_CONDITION_VARIABLES)
 | 
						|
		SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE);
 | 
						|
	#else
 | 
						|
		// TODO: broken, the unlock and wait need to be atomic
 | 
						|
		lock.unlock();
 | 
						|
		WaitForSingleObject(m_handle, INFINITE);
 | 
						|
		lock.lock();
 | 
						|
	#endif
 | 
						|
#else
 | 
						|
		pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
	template <class Predicate>
 | 
						|
	void wait(unique_lock<mutex>& lock, Predicate pred)
 | 
						|
	{
 | 
						|
		while (!pred())
 | 
						|
			wait(lock);
 | 
						|
	}
 | 
						|
 | 
						|
	//template <class Clock, class Duration>
 | 
						|
	//cv_status wait_until(unique_lock<mutex>& lock,
 | 
						|
	//	const chrono::time_point<Clock, Duration>& abs_time);
 | 
						|
 | 
						|
	//template <class Clock, class Duration, class Predicate>
 | 
						|
	//	bool wait_until(unique_lock<mutex>& lock,
 | 
						|
	//	const chrono::time_point<Clock, Duration>& abs_time,
 | 
						|
	//	Predicate pred);
 | 
						|
 | 
						|
	//template <class Rep, class Period>
 | 
						|
	//cv_status wait_for(unique_lock<mutex>& lock,
 | 
						|
	//	const chrono::duration<Rep, Period>& rel_time);
 | 
						|
 | 
						|
	//template <class Rep, class Period, class Predicate>
 | 
						|
	//	bool wait_for(unique_lock<mutex>& lock,
 | 
						|
	//	const chrono::duration<Rep, Period>& rel_time,
 | 
						|
	//	Predicate pred);
 | 
						|
	
 | 
						|
	native_handle_type native_handle()
 | 
						|
	{
 | 
						|
#ifdef USE_EVENTS
 | 
						|
		return m_handle;
 | 
						|
#else
 | 
						|
		return &m_handle;
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	native_type m_handle;
 | 
						|
};
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
#endif
 |