/* * 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 #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 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(head.buffer.data()), head.length); buffer_queue_.pop_front(); } }; }// namespace Utility #endif /* SKULLC_UTILITY_ASYNCLOGGER_HPP_ */