skullc-peripherals/Utility/Inc/utility_asynclogger.hpp
Erki 60bad24319
Some checks failed
continuous-integration/drone/push Build is failing
The great renaming, part 1
2021-06-08 23:18:56 +03:00

99 lines
1.9 KiB
C++

/*
* utility_asynclogger.hpp
*
* Created on: Apr 1, 2021
* Author: erki
*/
#ifndef SKULLC_UTILITY_ASYNCLOGGER_HPP_
#define SKULLC_UTILITY_ASYNCLOGGER_HPP_
#include "utility_atomicscopeguard.hpp"
#include "utility_ilogger.hpp"
#include "utility_ringbuffer.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_;
/// @todo: thread safety
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();
}
};
}// namespace Utility
#endif /* SKULLC_UTILITY_ASYNCLOGGER_HPP_ */