mpm: Add log_buf class

This is a buffer for log messages, designed for getting log messages
from C++ back into Python.

Reviewed-By: Mark Meserve <mark.meserve@ni.com>
This commit is contained in:
Martin Braun 2017-11-14 14:29:25 -08:00
parent bc85ad9df0
commit 5c63a83d22
4 changed files with 170 additions and 0 deletions

View File

@ -0,0 +1,87 @@
//
// Copyright 2017 Ettus Research, National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0
//
#pragma once
#include <boost/noncopyable.hpp>
#include <boost/circular_buffer.hpp>
#include <mutex>
#include <memory>
#include <tuple>
#include <functional>
namespace mpm { namespace types {
//! Log levels, designed to match the ones in mpmlog.py
enum class log_level_t {
NONE = 0, //!< Use this when there's actually no message
TRACE = 1,
DEBUG = 10,
INFO = 20,
WARNING = 30,
ERROR = 40,
CRITICAL = 50
};
struct log_message {
log_level_t log_level;
std::string component;
std::string message;
log_message(
const log_level_t log_level_,
const std::string& component_,
const std::string& message_
) : log_level(log_level_)
, component(component_)
, message(message_)
{
// nop
}
};
class log_buf : public boost::noncopyable
{
public:
using sptr = std::shared_ptr<log_buf>;
static const size_t BUFSIZE = 20;
log_buf() : _buf(BUFSIZE) {}
~log_buf() {}
static sptr make();
static sptr make_singleton();
/*! Post a message to the ring buffer
*
* \param log_level Log level
* \param component The component where the message is originating from
* \param message The actual log message
*/
void post(
const log_level_t log_level,
const std::string &component,
const std::string &message
);
//! Use this to set a callback that gets called when a new message was
// posted.
void set_notify_callback(
std::function<void(void)> callback
);
std::tuple<log_level_t, std::string, std::string> pop();
private:
std::mutex _buf_lock;
boost::circular_buffer<log_message> _buf;
std::function<void(void)> _notify_callback;
};
}} /* namespace mpm::types */

View File

@ -19,6 +19,7 @@
#include "lockable.hpp"
#include "regs_iface.hpp"
#include "log_buf.hpp"
void export_types() {
LIBMPM_BOOST_PREAMBLE("types")
@ -34,5 +35,22 @@ void export_types() {
.def("peek16", &regs_iface::peek16)
.def("poke16", &regs_iface::poke16)
;
bp::class_<log_buf, boost::noncopyable, std::shared_ptr<log_buf> >("log_buf", bp::no_init)
.def("make_singleton", &log_buf::make_singleton)
.staticmethod("make_singleton")
.def("set_notify_callback", +[](log_buf& self,
boost::python::object object) {
self.set_notify_callback(object);
})
.def("pop", +[](log_buf& self){
auto log_msg = self.pop();
return bp::make_tuple(
static_cast<int>(std::get<0>(log_msg)),
std::get<1>(log_msg),
std::get<2>(log_msg)
);
})
;
}

View File

@ -1,5 +1,6 @@
SET(TYPES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/lockable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/log_buf.cpp
)
USRP_PERIPHS_ADD_OBJECT(types ${TYPES_SOURCES})

64
mpm/lib/types/log_buf.cpp Normal file
View File

@ -0,0 +1,64 @@
//
// Copyright 2017 Ettus Research, National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0
//
#include <mpm/types/log_buf.hpp>
using namespace mpm::types;
void log_buf::post(
const log_level_t log_level,
const std::string &component,
const std::string &message
) {
{
std::lock_guard<std::mutex> l(_buf_lock);
_buf.push_back(
log_message(log_level, component, message)
);
}
if (bool(_notify_callback)) {
_notify_callback();
}
}
void log_buf::set_notify_callback(
std::function<void(void)> callback
) {
_notify_callback = callback;
}
std::tuple<log_level_t, std::string, std::string> log_buf::pop()
{
std::lock_guard<std::mutex> l(_buf_lock);
if (_buf.empty()) {
return std::make_tuple(
log_level_t::NONE,
"",
""
);
}
auto last_msg = _buf.front();
_buf.pop_front();
return std::make_tuple(
last_msg.log_level,
last_msg.component,
last_msg.message
);
}
log_buf::sptr log_buf::make()
{
return std::make_shared<log_buf>();
}
log_buf::sptr log_buf::make_singleton()
{
static auto log_sptr = log_buf::make();
return log_sptr;
}