如何组织从提升日志接收器进行线程安全读取?



我正在寻找一种正确的方法来安全地从boost::log::sinks::text_ostream_backend获取文本数据。 我目前仅在接收器后端记录了所有内容后才能获得数据。我想在仍然可以生成数据的同时获取后端内部缓冲区 (m_ss( 的副本。

using Logger = boost::log::sources::severity_channel_logger_mt<boost::log::trivial::severity_level, std::string>;
class MyClass
{
mutable std::mutex  m_mutex;
mutable Logger      m_logger {boost::log::keywords::channel = "MyClass"};
std::stringstream   m_ss;
bool                m_completed {false};
public:
void initLogging(const std::string& id)
{
using namespace boost::log;
using Sink = sinks::synchronous_sink<sinks::text_ostream_backend>;
auto backend = boost::make_shared<sinks::text_ostream_backend>();
backend->add_stream(boost::shared_ptr<std::stringstream>(&m_ss, boost::null_deleter()));
auto sink = boost::make_shared<Sink>(backend);
sink->set_filter(expressions::has_attr<std::string>("ID") && expressions::attr<std::string>("ID") == id);
core::get()->add_sink(sink);
m_logger.add_attribute("ID", attributes::constant<std::string>(id));
}
void doSomething()
{
BOOST_LOG_SEV(logger, boost::log::trivial::severity_level::debug) << "TEST";
BOOST_LOG_SEV(logger, boost::log::trivial::severity_level::error) << "TEST";
// Stop write logs
std::lock_guard<std::mutex> lock(m_mutex);
m_completed = true;
}
void access()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_completed) {
// Can read from stream
useStreamData(m_ss.str());
}
}
};

如果流仅由接收器后端访问,则同步访问的最简单方法是使用locked_backend

auto locked_backend = sink->locked_backend();

在这里,locked_backend对象是一个智能指针,它锁定接收器前端,因此阻止日志记录线程访问后端,从而阻止m_ss流。您可以在locked_backend存在时安全地使用m_ss

还有其他方法可以实现这一点。例如,可以实现自定义接收器后端或实现允许同步访问累积数据的流缓冲区。有许多关于编写自定义流缓冲区的文章和博客文章,下面是一个示例。

最新更新