....
-, . .
void thread_func()
{
std::unique_lock<std::mutex> lock(m);
while (!shouldExit) {
while (jobs.empty() && !shouldExit) {
cv.wait(lock);
}
if (jobs.empty()) {
continue;
}
if (!lock.owns_lock()) {
lock.lock();
}
auto j = std::move(jobs.front());
jobs.pop_front();
lock.unlock();
std::cout << "Do something with job " << j << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
{1} ... , {5}
{2} shouldExit bool. .
{3} - , , . unlock {5}. , .
{4} , , , .
{5} ... .
... {, ... }
lock.lock() thread_func()
....
void thread_func()
{
.....more code omitted
........
lock.unlock();
std::cout << "Do something with job " << j << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
lock.lock();
}
}
.... , , ... continue. , std::condition_variable::wait(), , ...
! !!!... !
std::cout , , ...
std::cout ? (. )
void thread_func()
{
std::unique_lock<std::mutex> lock(m);
while (!shouldExit)
{
while (jobs.empty() && !shouldExit)
{
cv.wait(lock, []{ return !jobs.empty(); } );
}
auto j = std::move(jobs.front());
jobs.pop_front();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
, , " " std::condition_variable::wait().
...
#include <thread>
#include <condition_variable>
#include <memory>
#include <iostream>
#include <list>
#include <atomic>
std::condition_variable cv;
std::mutex m;
std::mutex mxa;
std::thread t;
std::atomic<bool> shouldExit;
std::list<int> jobs;
namespace detail
{
std::ostream& safe_print()
{
return std::cout;
}
template<typename T, typename... Args>
std::ostream& safe_print(T&& t, Args&&... args)
{
std::cout << t;
return safe_print(std::forward<Args>(args)...);
}
}
template<typename... Args>
std::ostream& println(Args&&... args)
{
std::lock_guard<std::mutex> lck(mxa);
auto&& x = detail::safe_print(std::forward<Args>(args)...);
std::cout << std::endl;
return x;
}
void thread_func()
{
std::unique_lock<std::mutex> lock(m);
while (jobs.empty() && !shouldExit)
{
cv.wait(lock, []{ return !jobs.empty(); } );
}
auto j = std::move(jobs.front());
jobs.pop_front();
println("Do something with job ", j);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
int main()
{
shouldExit = false;
t = std::thread(thread_func);
for (int i = 1; i < 100; ++i)
{
println("Push to Job ", i);
{
std::lock_guard<std::mutex> lock(m);
jobs.push_back(i);
cv.notify_one();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
shouldExit = true;
cv.notify_one();
t.join();
return 0;
}