/* * 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_ilogger.hpp" #include "utility_ringbuffer.hpp" #include #include #include namespace Utility { template 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 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 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 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(head.buffer.data()), head.length); _buffer_queue.pop_front(); } }; }// namespace Utility #endif /* UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_ */