ESPHome 2026.4.0-dev
Loading...
Searching...
No Matches
task_log_buffer_host.h
Go to the documentation of this file.
1#pragma once
2
3#ifdef USE_HOST
4
7
8#ifdef USE_ESPHOME_TASK_LOG_BUFFER
9
10#include <atomic>
11#include <cstdarg>
12#include <cstddef>
13#include <cstring>
14#include <pthread.h>
15
16namespace esphome::logger {
17
50class TaskLogBuffer {
51 public:
52 // Structure for a log message (fixed size for lock-free operation)
53 struct LogMessage {
54 // Size constants
55 static constexpr size_t MAX_THREAD_NAME_SIZE = 32;
56 static constexpr size_t MAX_TEXT_SIZE = 512;
57
58 const char *tag; // Pointer to static tag string
59 char thread_name[MAX_THREAD_NAME_SIZE]; // Thread name (copied)
60 char text[MAX_TEXT_SIZE + 1]; // Message text with null terminator
61 uint16_t text_length; // Actual length of text
62 uint16_t line; // Source line number
63 uint8_t level; // Log level
64 std::atomic<bool> ready; // Message is ready to be consumed
65
66 LogMessage() : tag(nullptr), text_length(0), line(0), level(0), ready(false) {
67 thread_name[0] = '\0';
68 text[0] = '\0';
69 }
70 inline char *text_data() { return this->text; }
71 };
72
73 TaskLogBuffer() = default;
74
75 // NOT thread-safe - get next message from buffer, only call from main loop
76 // Returns true if a message was retrieved, false if buffer is empty
77 bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length);
78
79 // NOT thread-safe - release the message after processing, only call from main loop
81
82 // Thread-safe - send a message to the buffer from any thread
83 // Returns true if message was queued, false if buffer is full
84 bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
85 const char *format, va_list args);
86
87 // Check if there are messages ready to be processed
88 inline bool HOT has_messages() const {
89 return read_index_.load(std::memory_order_acquire) != write_index_.load(std::memory_order_acquire);
90 }
91
92 // Get the buffer size (number of slots)
93 static constexpr size_t size() { return ESPHOME_TASK_LOG_BUFFER_SIZE; }
94
95 private:
96 // Acquire a slot for writing (thread-safe)
97 // Returns slot index or -1 if buffer is full
98 int acquire_write_slot_();
99
100 // Commit a slot after writing (thread-safe)
101 void commit_write_slot_(int slot_index);
102
103 LogMessage slots_[ESPHOME_TASK_LOG_BUFFER_SIZE]; // Embedded in Logger (no separate heap allocation)
104
105 // Lock-free indices using atomics
106 // - reserve_index_: Next slot to reserve (producers CAS this to claim slots)
107 // - write_index_: Boundary of committed/ready slots (consumer reads up to this)
108 // - read_index_: Next slot to read (only consumer modifies this)
109 std::atomic<size_t> reserve_index_{0}; // Next slot to reserve for writing
110 std::atomic<size_t> write_index_{0}; // Last committed slot boundary
111 std::atomic<size_t> read_index_{0}; // Next slot to read from
112};
113
114} // namespace esphome::logger
115
116#endif // USE_ESPHOME_TASK_LOG_BUFFER
117#endif // USE_HOST
bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length)
bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args)
static constexpr size_t size()
const char * message
Definition component.cpp:35
const char int line
Definition log.h:74
const char * tag
Definition log.h:74
const char int const __FlashStringHelper * format
Definition log.h:74
const char int const __FlashStringHelper va_list args
Definition log.h:74