std::condition_variable wait_until timeout или наступление события
Не ругайте сильно, это, практически первая попытка написать что-то многопоточное. Сделал некий класс Logger
#include <iostream>
#include <thread>
#include <atomic>
#include <unistd.h>
#include <csignal>
#include <memory>
#include <list>
#include <mutex>
#include <condition_variable>
using std::cout;
using std::endl;
using std::unitbuf;
std::atomic_bool g_stop{false};
class Logger
{
public:
~Logger() {};
static Logger* get_logger()
{
static Logger logger;
return &logger;
}
void log(const std::string& _msg)
{
std::unique_lock<std::mutex> ul(m_msg_mutex);
m_messages.push_back(_msg);
cout << unitbuf << "--- added " << _msg << " size: " << m_messages.size() << endl;
}
void log_job(std::atomic_bool& stop)
{
while (!stop)
{
log("Logger OK");
std::unique_lock<std::mutex> ul(m_cv_mutex);
{
m_cv.wait_for(ul, std::chrono::seconds(m_interval), [&]() { return (m_messages.size() >= m_limit); });
flush();
}
}
flush();
cout << unitbuf << "Logger exited" << endl;
}
protected:
std::list<std::string> m_messages;
const unsigned int m_limit {12};
const unsigned int m_interval {3};
std::condition_variable m_cv;
std::mutex m_cv_mutex;
std::mutex m_msg_mutex;
Logger() {};
Logger(const Logger& _obj); // no copies
const Logger& operator=(const Logger& _obj); // no assignment
void flush()
{
std::unique_lock<std::mutex> ul(m_msg_mutex);
for (const std::string& s: m_messages) cout << unitbuf << s << endl;
m_messages.clear();
}
};
class Device
{
public:
Device(){}
void job(std::atomic_bool& stop)
{
Logger* logger {Logger::get_logger()};
int cnt {0};
while (!stop)
{
std::string s = std::string("msg") + std::to_string(cnt++);
logger->log(s);
usleep(200000);
}
}
};
void sig_handler(int _sig)
{
switch (_sig)
{
case SIGTERM:
g_stop = true;
break;
default:
cout << "No, no, no, David Blaine, no street magic!" << endl;
}
}
int main()
{
signal(SIGTERM, sig_handler);
Logger* logger = Logger::get_logger();
std::thread thr([&]() {
logger->log_job(g_stop);
});
Device d;
std::thread jtht(&Device::job, d, std::ref(g_stop));
jtht.join();
thr.join();
return 0;
}
Хочется задать условие, при котором цикл будет повторяться при тайм-ауте или превышении размера m_msgs
. Подскажите, как такое сделать. Заранее благодарен.
UPD: компилятор - не старше c++14 и нет возможности обновить.
Источник: Stack Overflow на русском