ESPHome 2026.1.4
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 <memory>
15#include <pthread.h>
16
17namespace esphome::logger {
18
52 public:
53 // Default number of message slots - host has plenty of memory
54 static constexpr size_t DEFAULT_SLOT_COUNT = 64;
55
56 // Structure for a log message (fixed size for lock-free operation)
57 struct LogMessage {
58 // Size constants
59 static constexpr size_t MAX_THREAD_NAME_SIZE = 32;
60 static constexpr size_t MAX_TEXT_SIZE = 512;
61
62 const char *tag; // Pointer to static tag string
63 char thread_name[MAX_THREAD_NAME_SIZE]; // Thread name (copied)
64 char text[MAX_TEXT_SIZE + 1]; // Message text with null terminator
65 uint16_t text_length; // Actual length of text
66 uint16_t line; // Source line number
67 uint8_t level; // Log level
68 std::atomic<bool> ready; // Message is ready to be consumed
69
70 LogMessage() : tag(nullptr), text_length(0), line(0), level(0), ready(false) {
71 thread_name[0] = '\0';
72 text[0] = '\0';
73 }
74 };
75
77 explicit TaskLogBufferHost(size_t slot_count);
79
80 // NOT thread-safe - get next message from buffer, only call from main loop
81 // Returns true if a message was retrieved, false if buffer is empty
82 bool get_message_main_loop(LogMessage **message);
83
84 // NOT thread-safe - release the message after processing, only call from main loop
86
87 // Thread-safe - send a message to the buffer from any thread
88 // Returns true if message was queued, false if buffer is full
89 bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *format, va_list args);
90
91 // Check if there are messages ready to be processed
92 inline bool HOT has_messages() const {
93 return read_index_.load(std::memory_order_acquire) != write_index_.load(std::memory_order_acquire);
94 }
95
96 // Get the buffer size (number of slots)
97 inline size_t size() const { return slot_count_; }
98
99 private:
100 // Acquire a slot for writing (thread-safe)
101 // Returns slot index or -1 if buffer is full
102 int acquire_write_slot_();
103
104 // Commit a slot after writing (thread-safe)
105 void commit_write_slot_(int slot_index);
106
107 std::unique_ptr<LogMessage[]> slots_; // Pre-allocated message slots
108 size_t slot_count_; // Number of slots
109
110 // Lock-free indices using atomics
111 // - reserve_index_: Next slot to reserve (producers CAS this to claim slots)
112 // - write_index_: Boundary of committed/ready slots (consumer reads up to this)
113 // - read_index_: Next slot to read (only consumer modifies this)
114 std::atomic<size_t> reserve_index_{0}; // Next slot to reserve for writing
115 std::atomic<size_t> write_index_{0}; // Last committed slot boundary
116 std::atomic<size_t> read_index_{0}; // Next slot to read from
117};
118
119} // namespace esphome::logger
120
121#endif // USE_ESPHOME_TASK_LOG_BUFFER
122#endif // USE_HOST
Lock-free task log buffer for host platform.
static constexpr size_t DEFAULT_SLOT_COUNT
bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *format, va_list args)
TaskLogBufferHost(size_t slot_count)
Constructor that takes the number of message slots.
bool get_message_main_loop(LogMessage **message)
const char * message
Definition component.cpp:38