| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | // Copyright 2014 Dolphin Emulator Project
 | 
					
						
							| 
									
										
										
										
											2015-05-18 01:08:10 +02:00
										 |  |  | // Licensed under GPLv2+
 | 
					
						
							| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Multithreaded event class. This allows waiting in a thread for an event to
 | 
					
						
							|  |  |  | // be triggered in another thread. While waiting, the CPU will be available for
 | 
					
						
							|  |  |  | // other tasks.
 | 
					
						
							|  |  |  | // * Set(): triggers the event and wakes up the waiting thread.
 | 
					
						
							|  |  |  | // * Wait(): waits for the event to be triggered.
 | 
					
						
							|  |  |  | // * Reset(): tries to reset the event before the waiting thread sees it was
 | 
					
						
							|  |  |  | //            triggered. Usually a bad idea.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-14 02:30:40 +02:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | #include <concrt.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-12 22:53:17 -07:00
										 |  |  | #include <chrono>
 | 
					
						
							| 
									
										
										
										
											2014-08-14 01:14:35 -04:00
										 |  |  | #include <condition_variable>
 | 
					
						
							|  |  |  | #include <mutex>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-14 01:42:03 +02:00
										 |  |  | #include "Common/Flag.h"
 | 
					
						
							| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | namespace Common | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-14 02:30:40 +02:00
										 |  |  | class Event final | 
					
						
							| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   void Set() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_flag.TestAndSet()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       std::lock_guard<std::mutex> lk(m_mutex); | 
					
						
							|  |  |  |       m_condvar.notify_one(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   void Wait() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_flag.TestAndClear()) | 
					
						
							|  |  |  |       return; | 
					
						
							| 
									
										
										
										
											2014-04-14 01:42:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     std::unique_lock<std::mutex> lk(m_mutex); | 
					
						
							|  |  |  |     m_condvar.wait(lk, [&] { return m_flag.TestAndClear(); }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   template <class Rep, class Period> | 
					
						
							|  |  |  |   bool WaitFor(const std::chrono::duration<Rep, Period>& rel_time) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_flag.TestAndClear()) | 
					
						
							|  |  |  |       return true; | 
					
						
							| 
									
										
										
										
											2014-08-12 22:53:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     std::unique_lock<std::mutex> lk(m_mutex); | 
					
						
							|  |  |  |     bool signaled = m_condvar.wait_for(lk, rel_time, [&] { return m_flag.TestAndClear(); }); | 
					
						
							| 
									
										
										
										
											2014-08-12 22:53:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return signaled; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-12 22:53:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   void Reset() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // no other action required, since wait loops on
 | 
					
						
							|  |  |  |     // the predicate and any lingering signal will get
 | 
					
						
							|  |  |  |     // cleared on the first iteration
 | 
					
						
							|  |  |  |     m_flag.Clear(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   Flag m_flag; | 
					
						
							|  |  |  |   std::condition_variable m_condvar; | 
					
						
							|  |  |  |   std::mutex m_mutex; | 
					
						
							| 
									
										
										
										
											2014-04-14 01:15:23 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace Common
 |