#include <iostream>
#include <thread>
#include <iostream>
#include <condition_variable>
#include <list>
using namespace std;
class Worker
{
public:
Worker(bool run) : m_Running(run) { if (run) private_start(); }
Worker() : m_Running(false) { }
~Worker() { stop(); }
template<typename... Args>
void push_task(Args&&... args)
{
{
std::lock_guard<std::mutex> lk(m_Mutex);
m_Queue.push_back(std::bind(std::forward<Args>(args)...));
}
m_Condition.notify_all();
}
void start()
{
{
std::lock_guard<std::mutex> lk(m_Mutex);
if (m_Running == true) return;
m_Running = true;
}
private_start();
}
void stop()
{
{
std::lock_guard<std::mutex> lk(m_Mutex);
if (m_Running == false) return;
m_Running = false;
}
m_Condition.notify_all();
m_Thread.join();
}
private:
void private_start()
{
m_Thread = std::thread([this]
{
for (;;)
{
decltype(m_Queue) local_queue;
{
std::unique_lock<std::mutex> lk(m_Mutex);
m_Condition.wait(lk, [&] { return !m_Queue.empty() + !m_Running; });
if (!m_Running)
{
for (auto& func : m_Queue)
func();
m_Queue.clear();
return;
}
std::swap(m_Queue, local_queue);
}
for (auto& func : local_queue)
func();
}
});
}
private:
std::condition_variable m_Condition;
std::list<std::function<void()>> m_Queue;
std::mutex m_Mutex;
std::thread m_Thread;
bool m_Running = false;
};
void do_work(unsigned id)
{
// uncomment if you want to sync the output stream
// static std::mutex cout_mutex;
// std::lock_guard<std::mutex> lk(cout_mutex);
std::cout << id << std::endl;
}
int main()
{
{
Worker workers[3];
int counter = 0;
for (auto& worker : workers)
worker.start();
for (auto& worker : workers)
{
for (int i = 0; i < 5; i++)
worker.push_task(do_work, ++counter + i);
}
}
std::cout << "finish" << std::endl;
getchar();
return 0;
}