forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			87 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2017 Dolphin Emulator Project
 | |
| // Licensed under GPLv2+
 | |
| // Refer to the license.txt file included.
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <functional>
 | |
| #include <queue>
 | |
| #include <thread>
 | |
| 
 | |
| #include "Common/Event.h"
 | |
| #include "Common/Flag.h"
 | |
| 
 | |
| // A thread that executes the given function for every item placed into its queue.
 | |
| 
 | |
| namespace Common
 | |
| {
 | |
| template <typename T>
 | |
| class WorkQueueThread
 | |
| {
 | |
| public:
 | |
|   WorkQueueThread() = default;
 | |
|   WorkQueueThread(std::function<void(T)> function) { Reset(std::move(function)); }
 | |
|   ~WorkQueueThread() { Shutdown(); }
 | |
|   void Reset(std::function<void(T)> function)
 | |
|   {
 | |
|     Shutdown();
 | |
|     m_shutdown.Clear();
 | |
|     m_function = std::move(function);
 | |
|     m_thread = std::thread([this] { ThreadLoop(); });
 | |
|   }
 | |
| 
 | |
|   template <typename... Args>
 | |
|   void EmplaceItem(Args&&... args)
 | |
|   {
 | |
|     {
 | |
|       std::unique_lock<std::mutex> lg(m_lock);
 | |
|       m_items.emplace(std::forward<Args>(args)...);
 | |
|     }
 | |
|     m_wakeup.Set();
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   void Shutdown()
 | |
|   {
 | |
|     if (m_thread.joinable())
 | |
|     {
 | |
|       m_shutdown.Set();
 | |
|       m_wakeup.Set();
 | |
|       m_thread.join();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void ThreadLoop()
 | |
|   {
 | |
|     while (true)
 | |
|     {
 | |
|       m_wakeup.Wait();
 | |
| 
 | |
|       while (true)
 | |
|       {
 | |
|         T item;
 | |
|         {
 | |
|           std::unique_lock<std::mutex> lg(m_lock);
 | |
|           if (m_items.empty())
 | |
|             break;
 | |
|           item = m_items.front();
 | |
|           m_items.pop();
 | |
|         }
 | |
|         m_function(std::move(item));
 | |
|       }
 | |
| 
 | |
|       if (m_shutdown.IsSet())
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   std::function<void(T)> m_function;
 | |
|   std::thread m_thread;
 | |
|   Common::Event m_wakeup;
 | |
|   Common::Flag m_shutdown;
 | |
|   std::mutex m_lock;
 | |
|   std::queue<T> m_items;
 | |
| };
 | |
| 
 | |
| }  // namespace Common
 |