skullc-peripherals/Utility/Inc/utility_asynclogger.hpp

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);
_Data& tail = (*_buffer_queue.end());
tail.length = vsnprintf(tail.buffer.data(), tail.buffer.size(), format, args);
{
AtomicScopeGuard<hal> s;
_buffer_queue.increment_tail();
if (!_in_flight)
_sendNextLog();
}
va_end(args);
}
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_ */