skullc-peripherals/Utility/Inc/utility_asynclogger.hpp
Erki ce4f8eb8f5
All checks were successful
continuous-integration/drone/push Build is passing
New logging interfaces
2021-04-02 00:50:59 +03:00

98 lines
1.9 KiB
C++

/*
* utility_asynclogger.hpp
*
* Created on: Apr 1, 2021
* Author: erki
*/
#ifndef UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_
#define UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_
#include "utility_atomicscopeguard.hpp"
#include "utility_ringbuffer.hpp"
#include "utility_ilogger.hpp"
#include <array>
#include <cstdarg>
#include <cstdio>
namespace Utility
{
template<typename T, typename H, std::size_t BufferCount, std::size_t BufferSize>
class AsyncLogger : public ILogger
{
public:
using serial_interface = T;
using hal = H;
AsyncLogger() = delete;
explicit AsyncLogger(const serial_interface& serial)
: _serial(serial)
{ }
AsyncLogger(const AsyncLogger&) = delete;
AsyncLogger(AsyncLogger&&) = delete;
AsyncLogger& operator=(const AsyncLogger&) = delete;
AsyncLogger& operator=(AsyncLogger&&) = delete;
void log(const char* format, ...)
{
{
AtomicScopeGuard<hal> s;
if (_buffer_queue.size() == _buffer_queue.max_size())
return;
}
std::va_list args;
va_start(args, format);
auto tail = _buffer_queue.end();
std::array<char, 255>& buffer = tail->buffer;
tail->length = vsnprintf(buffer.data(), buffer.size(), format, args);
{
AtomicScopeGuard<hal> s;
_buffer_queue.increment_tail();
if (!_in_flight)
_sendNextLog();
}
}
void txCompleteCallback()
{
if (!_buffer_queue.empty())
_sendNextLog();
else
_in_flight = false;
}
private:
struct _Data
{
std::array<char, BufferSize> buffer;
std::int32_t length = 0;
};
Ringbuffer<_Data, BufferCount> _buffer_queue;
serial_interface _serial;
bool _in_flight = false;
void _sendNextLog()
{
_in_flight = true;
_Data& head = _buffer_queue.front();
_serial.Transmit(reinterpret_cast<uint8_t*>(head.buffer.data()), head.length);
_buffer_queue.pop_front();
}
};
}
#endif /* UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_ */